@brandlab-digital/site-next 3.7.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/instrumentation-client.d.ts +23 -4
  2. package/dist/instrumentation-client.d.ts.map +1 -1
  3. package/dist/instrumentation-client.js +65 -3
  4. package/dist/instrumentation-client.js.map +1 -1
  5. package/dist/navigation/constants.d.ts +25 -0
  6. package/dist/navigation/constants.d.ts.map +1 -0
  7. package/dist/navigation/constants.js +30 -0
  8. package/dist/navigation/constants.js.map +1 -0
  9. package/dist/navigation/index.d.ts +11 -0
  10. package/dist/navigation/index.d.ts.map +1 -0
  11. package/dist/navigation/index.js +11 -0
  12. package/dist/navigation/index.js.map +1 -0
  13. package/dist/navigation/use-back-to-top.d.ts +5 -0
  14. package/dist/navigation/use-back-to-top.d.ts.map +1 -0
  15. package/dist/navigation/use-back-to-top.js +32 -0
  16. package/dist/navigation/use-back-to-top.js.map +1 -0
  17. package/dist/navigation/use-header-metrics.d.ts +17 -0
  18. package/dist/navigation/use-header-metrics.d.ts.map +1 -0
  19. package/dist/navigation/use-header-metrics.js +52 -0
  20. package/dist/navigation/use-header-metrics.js.map +1 -0
  21. package/dist/navigation/use-navigation-menu.d.ts +39 -0
  22. package/dist/navigation/use-navigation-menu.d.ts.map +1 -0
  23. package/dist/navigation/use-navigation-menu.js +206 -0
  24. package/dist/navigation/use-navigation-menu.js.map +1 -0
  25. package/dist/navigation/use-sticky-call-bar.d.ts +15 -0
  26. package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -0
  27. package/dist/navigation/use-sticky-call-bar.js +110 -0
  28. package/dist/navigation/use-sticky-call-bar.js.map +1 -0
  29. package/dist/ui-kit/brandlab-skin.d.ts +27 -0
  30. package/dist/ui-kit/brandlab-skin.d.ts.map +1 -0
  31. package/dist/ui-kit/brandlab-skin.js +2 -0
  32. package/dist/ui-kit/brandlab-skin.js.map +1 -0
  33. package/dist/ui-kit/icons.d.ts +15 -0
  34. package/dist/ui-kit/icons.d.ts.map +1 -0
  35. package/dist/ui-kit/icons.js +72 -0
  36. package/dist/ui-kit/icons.js.map +1 -0
  37. package/dist/ui-kit/primitives/index.d.ts +6 -0
  38. package/dist/ui-kit/primitives/index.d.ts.map +1 -0
  39. package/dist/ui-kit/primitives/index.js +6 -0
  40. package/dist/ui-kit/primitives/index.js.map +1 -0
  41. package/dist/ui-kit/primitives/layout.d.ts +73 -0
  42. package/dist/ui-kit/primitives/layout.d.ts.map +1 -0
  43. package/dist/ui-kit/primitives/layout.js +34 -0
  44. package/dist/ui-kit/primitives/layout.js.map +1 -0
  45. package/dist/ui-kit/primitives/links.d.ts +48 -0
  46. package/dist/ui-kit/primitives/links.d.ts.map +1 -0
  47. package/dist/ui-kit/primitives/links.js +36 -0
  48. package/dist/ui-kit/primitives/links.js.map +1 -0
  49. package/dist/ui-kit/primitives/quote-button.d.ts +20 -0
  50. package/dist/ui-kit/primitives/quote-button.d.ts.map +1 -0
  51. package/dist/ui-kit/primitives/quote-button.js +15 -0
  52. package/dist/ui-kit/primitives/quote-button.js.map +1 -0
  53. package/dist/ui-kit/shell/back-to-top-client.d.ts +9 -0
  54. package/dist/ui-kit/shell/back-to-top-client.d.ts.map +1 -0
  55. package/dist/ui-kit/shell/back-to-top-client.js +8 -0
  56. package/dist/ui-kit/shell/back-to-top-client.js.map +1 -0
  57. package/dist/ui-kit/shell/back-to-top.d.ts +13 -0
  58. package/dist/ui-kit/shell/back-to-top.d.ts.map +1 -0
  59. package/dist/ui-kit/shell/back-to-top.js +14 -0
  60. package/dist/ui-kit/shell/back-to-top.js.map +1 -0
  61. package/dist/ui-kit/shell/call-bar-client.d.ts +7 -0
  62. package/dist/ui-kit/shell/call-bar-client.d.ts.map +1 -0
  63. package/dist/ui-kit/shell/call-bar-client.js +13 -0
  64. package/dist/ui-kit/shell/call-bar-client.js.map +1 -0
  65. package/dist/ui-kit/shell/current-link.d.ts +15 -0
  66. package/dist/ui-kit/shell/current-link.d.ts.map +1 -0
  67. package/dist/ui-kit/shell/current-link.js +34 -0
  68. package/dist/ui-kit/shell/current-link.js.map +1 -0
  69. package/dist/ui-kit/shell/drawer-client.d.ts +22 -0
  70. package/dist/ui-kit/shell/drawer-client.d.ts.map +1 -0
  71. package/dist/ui-kit/shell/drawer-client.js +70 -0
  72. package/dist/ui-kit/shell/drawer-client.js.map +1 -0
  73. package/dist/ui-kit/shell/header-client.d.ts +44 -0
  74. package/dist/ui-kit/shell/header-client.d.ts.map +1 -0
  75. package/dist/ui-kit/shell/header-client.js +59 -0
  76. package/dist/ui-kit/shell/header-client.js.map +1 -0
  77. package/dist/ui-kit/shell/index.d.ts +6 -0
  78. package/dist/ui-kit/shell/index.d.ts.map +1 -0
  79. package/dist/ui-kit/shell/index.js +6 -0
  80. package/dist/ui-kit/shell/index.js.map +1 -0
  81. package/dist/ui-kit/shell/mobile-call-bar.d.ts +16 -0
  82. package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -0
  83. package/dist/ui-kit/shell/mobile-call-bar.js +15 -0
  84. package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -0
  85. package/dist/ui-kit/shell/mobile-drawer.d.ts +37 -0
  86. package/dist/ui-kit/shell/mobile-drawer.d.ts.map +1 -0
  87. package/dist/ui-kit/shell/mobile-drawer.js +25 -0
  88. package/dist/ui-kit/shell/mobile-drawer.js.map +1 -0
  89. package/dist/ui-kit/shell/shell-context.d.ts +3 -0
  90. package/dist/ui-kit/shell/shell-context.d.ts.map +1 -0
  91. package/dist/ui-kit/shell/shell-context.js +5 -0
  92. package/dist/ui-kit/shell/shell-context.js.map +1 -0
  93. package/dist/ui-kit/shell/site-header.d.ts +52 -0
  94. package/dist/ui-kit/shell/site-header.d.ts.map +1 -0
  95. package/dist/ui-kit/shell/site-header.js +36 -0
  96. package/dist/ui-kit/shell/site-header.js.map +1 -0
  97. package/dist/ui-kit/shell/social-links.d.ts +8 -0
  98. package/dist/ui-kit/shell/social-links.d.ts.map +1 -0
  99. package/dist/ui-kit/shell/social-links.js +9 -0
  100. package/dist/ui-kit/shell/social-links.js.map +1 -0
  101. package/dist/ui-kit/shell/utility-bar.d.ts +30 -0
  102. package/dist/ui-kit/shell/utility-bar.d.ts.map +1 -0
  103. package/dist/ui-kit/shell/utility-bar.js +15 -0
  104. package/dist/ui-kit/shell/utility-bar.js.map +1 -0
  105. package/dist/ui-kit/skin-index.d.ts +3 -0
  106. package/dist/ui-kit/skin-index.d.ts.map +1 -0
  107. package/dist/ui-kit/skin-index.js +2 -0
  108. package/dist/ui-kit/skin-index.js.map +1 -0
  109. package/dist/ui-kit/skin.d.ts +48 -0
  110. package/dist/ui-kit/skin.d.ts.map +1 -0
  111. package/dist/ui-kit/skin.js +47 -0
  112. package/dist/ui-kit/skin.js.map +1 -0
  113. package/dist/ui-kit/structure.css +717 -0
  114. package/dist/ui-kit/types.d.ts +27 -0
  115. package/dist/ui-kit/types.d.ts.map +1 -0
  116. package/dist/ui-kit/types.js +6 -0
  117. package/dist/ui-kit/types.js.map +1 -0
  118. package/package.json +25 -4
@@ -0,0 +1,44 @@
1
+ import { type ReactNode } from 'react';
2
+ /** The `<header>` root: measures the header (mode, height, compact) and shares its mode. */
3
+ export declare function HeaderRoot({ variant, navAlign, compactAfterScroll, className, children, }: {
4
+ readonly variant: string;
5
+ readonly navAlign: string;
6
+ readonly compactAfterScroll: boolean;
7
+ readonly className?: string | undefined;
8
+ readonly children: ReactNode;
9
+ }): import("react/jsx-runtime").JSX.Element;
10
+ /** The `<nav>` landmark and the menu state (F3 engine) for the items inside it. */
11
+ export declare function NavController({ label, className, children }: {
12
+ readonly label: string;
13
+ readonly className?: string | undefined;
14
+ readonly children: ReactNode;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ /**
17
+ * One top-level item. `data-current` marks the current section: the page is the item's hub or one of its active
18
+ * paths (or below them), or one of its panel links is the current page.
19
+ */
20
+ export declare function NavItem({ menuId, paths, className, children, }: {
21
+ /** Set for an item with a panel. */
22
+ readonly menuId?: string;
23
+ readonly paths: readonly string[];
24
+ readonly className?: string | undefined;
25
+ readonly children: ReactNode;
26
+ }): import("react/jsx-runtime").JSX.Element;
27
+ /** The disclosure button beside an item's hub link, named "{label} menu". */
28
+ export declare function NavTrigger({ menuId, panelId, label, className, children, }: {
29
+ readonly menuId: string;
30
+ readonly panelId: string;
31
+ readonly label: string;
32
+ readonly className?: string | undefined;
33
+ readonly children: ReactNode;
34
+ }): import("react/jsx-runtime").JSX.Element;
35
+ /** The panel box. Its links are the server-rendered children; the panel only changes state. */
36
+ export declare function NavPanel({ menuId, panelId, variant, columns, className, children, }: {
37
+ readonly menuId: string;
38
+ readonly panelId: string;
39
+ readonly variant: string;
40
+ readonly columns?: number | undefined;
41
+ readonly className?: string | undefined;
42
+ readonly children: ReactNode;
43
+ }): import("react/jsx-runtime").JSX.Element;
44
+ //# sourceMappingURL=header-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-client.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/header-client.tsx"],"names":[],"mappings":"AASA,OAAO,EAA0D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAM9F,4FAA4F;AAC5F,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,kBAAkB,EAClB,SAAS,EACT,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAA;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B,2CAQA;AASD,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAY9J;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACtB,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,GACT,EAAE;IACD,oCAAoC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B,2CAuBA;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,EACzB,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,EACT,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B,2CAgBA;AAED,+FAA+F;AAC/F,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;CAC7B,2CAkBA"}
@@ -0,0 +1,59 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * The header's client leaves. They receive ids, labels, flags and class strings only; every link and panel is
5
+ * server-rendered and passed in as `children`. The leaves toggle `data-state`, `aria-expanded` and `inert` on those
6
+ * server nodes, so opening a panel never re-renders its links. `inert` is added only after hydration: closed panels
7
+ * are `visibility: hidden` in the server HTML, and inert content would break the pre-hydration hover fallback.
8
+ */
9
+ import { usePathname } from 'next/navigation';
10
+ import { createContext, useContext, useEffect, useRef, useState } from 'react';
11
+ import { useHeaderMetrics } from '../../navigation/use-header-metrics.js';
12
+ import { useNavigationMenu } from '../../navigation/use-navigation-menu.js';
13
+ import { isCurrentSection } from './current-link.js';
14
+ import { HeaderModeContext } from './shell-context.js';
15
+ /** The `<header>` root: measures the header (mode, height, compact) and shares its mode. */
16
+ export function HeaderRoot({ variant, navAlign, compactAfterScroll, className, children, }) {
17
+ const ref = useRef(null);
18
+ const { mode } = useHeaderMetrics(ref, { compactAfterScroll });
19
+ return (_jsx("header", { ref: ref, "data-bl": "header", "data-variant": variant, "data-nav-align": navAlign, className: className, children: _jsx(HeaderModeContext, { value: mode, children: children }) }));
20
+ }
21
+ const NavContext = createContext(null);
22
+ /** The `<nav>` landmark and the menu state (F3 engine) for the items inside it. */
23
+ export function NavController({ label, className, children }) {
24
+ const navRef = useRef(null);
25
+ const pathname = usePathname();
26
+ const mode = useContext(HeaderModeContext);
27
+ const menu = useNavigationMenu(navRef, `${pathname}|${mode}`);
28
+ const [hydrated, setHydrated] = useState(false);
29
+ useEffect(() => setHydrated(true), []);
30
+ return (_jsx("nav", { ref: navRef, "aria-label": label, "data-slot": "nav", className: className, children: _jsx(NavContext, { value: { menu, hydrated }, children: children }) }));
31
+ }
32
+ /**
33
+ * One top-level item. `data-current` marks the current section: the page is the item's hub or one of its active
34
+ * paths (or below them), or one of its panel links is the current page.
35
+ */
36
+ export function NavItem({ menuId, paths, className, children, }) {
37
+ const ref = useRef(null);
38
+ const pathname = usePathname();
39
+ const nav = useContext(NavContext);
40
+ const [panelLinkCurrent, setPanelLinkCurrent] = useState(false);
41
+ useEffect(() => {
42
+ setPanelLinkCurrent(ref.current?.querySelector('[data-slot="panel"] [aria-current="page"]') != null);
43
+ }, [pathname]);
44
+ const current = panelLinkCurrent || isCurrentSection(pathname, paths);
45
+ const open = menuId !== undefined && nav?.menu.openId === menuId;
46
+ return (_jsx("li", { ref: ref, "data-slot": "item", "data-has-panel": menuId !== undefined ? 'true' : undefined, "data-state": menuId !== undefined ? (open ? 'open' : 'closed') : undefined, "data-current": current ? 'true' : undefined, className: className, ...(menuId !== undefined && nav ? nav.menu.itemHandlers(menuId) : {}), children: children }));
47
+ }
48
+ /** The disclosure button beside an item's hub link, named "{label} menu". */
49
+ export function NavTrigger({ menuId, panelId, label, className, children, }) {
50
+ const nav = useContext(NavContext);
51
+ return (_jsx("button", { type: "button", "data-slot": "trigger", "data-menu-id": menuId, "aria-expanded": nav?.menu.openId === menuId, "aria-controls": panelId, "aria-label": `${label} menu`, className: className, ...nav?.menu.triggerHandlers(menuId), children: children }));
52
+ }
53
+ /** The panel box. Its links are the server-rendered children; the panel only changes state. */
54
+ export function NavPanel({ menuId, panelId, variant, columns, className, children, }) {
55
+ const nav = useContext(NavContext);
56
+ const open = nav?.menu.openId === menuId;
57
+ return (_jsx("div", { id: panelId, "data-slot": "panel", "data-menu-id": menuId, "data-variant": variant, "data-columns": columns, "data-state": open ? 'open' : 'closed', inert: Boolean(nav?.hydrated) && !open, className: className, ...nav?.menu.panelHandlers(menuId), children: children }));
58
+ }
59
+ //# sourceMappingURL=header-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-client.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/header-client.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;GAKG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAC9F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAuB,MAAM,yCAAyC,CAAA;AAChG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAEtD,4FAA4F;AAC5F,MAAM,UAAU,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,kBAAkB,EAClB,SAAS,EACT,QAAQ,GAOT;IACC,MAAM,GAAG,GAAG,MAAM,CAAc,IAAI,CAAC,CAAA;IACrC,MAAM,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAAC,GAAG,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAA;IAC9D,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,aAAU,QAAQ,kBAAe,OAAO,oBAAkB,QAAQ,EAAE,SAAS,EAAE,SAAS,YACtG,KAAC,iBAAiB,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAAqB,GACvD,CACV,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,GAAG,aAAa,CAAkB,IAAI,CAAC,CAAA;AAEvD,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAqG;IAC7J,MAAM,MAAM,GAAG,MAAM,CAAc,IAAI,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,IAAI,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAA;IAC1C,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,EAAE,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/C,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO,CACL,cAAK,GAAG,EAAE,MAAM,gBAAc,KAAK,eAAY,KAAK,EAAC,SAAS,EAAE,SAAS,YACvE,KAAC,UAAU,IAAC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAG,QAAQ,GAAc,GAC1D,CACP,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,MAAM,EACN,KAAK,EACL,SAAS,EACT,QAAQ,GAOT;IACC,MAAM,GAAG,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAA;IACvC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC/D,SAAS,CAAC,GAAG,EAAE;QACb,mBAAmB,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,2CAA2C,CAAC,IAAI,IAAI,CAAC,CAAA;IACtG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IACd,MAAM,OAAO,GAAG,gBAAgB,IAAI,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;IACrE,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,IAAI,GAAG,EAAE,IAAI,CAAC,MAAM,KAAK,MAAM,CAAA;IAChE,OAAO,CACL,aACE,GAAG,EAAE,GAAG,eACE,MAAM,oBACA,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,gBAC7C,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,kBAC3D,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAC1C,SAAS,EAAE,SAAS,KAChB,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAErE,QAAQ,GACN,CACN,CAAA;AACH,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,EACzB,MAAM,EACN,OAAO,EACP,KAAK,EACL,SAAS,EACT,QAAQ,GAOT;IACC,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;IAClC,OAAO,CACL,iBACE,IAAI,EAAC,QAAQ,eACH,SAAS,kBACL,MAAM,mBACL,GAAG,EAAE,IAAI,CAAC,MAAM,KAAK,MAAM,mBAC3B,OAAO,gBACV,GAAG,KAAK,OAAO,EAC3B,SAAS,EAAE,SAAS,KAChB,GAAG,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,YAEpC,QAAQ,GACF,CACV,CAAA;AACH,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,QAAQ,CAAC,EACvB,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,SAAS,EACT,QAAQ,GAQT;IACC,MAAM,GAAG,GAAG,UAAU,CAAC,UAAU,CAAC,CAAA;IAClC,MAAM,IAAI,GAAG,GAAG,EAAE,IAAI,CAAC,MAAM,KAAK,MAAM,CAAA;IACxC,OAAO,CACL,cACE,EAAE,EAAE,OAAO,eACD,OAAO,kBACH,MAAM,kBACN,OAAO,kBACP,OAAO,gBACT,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EACpC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EACtC,SAAS,EAAE,SAAS,KAChB,GAAG,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,YAElC,QAAQ,GACL,CACP,CAAA;AACH,CAAC","sourcesContent":["'use client'\n\n/**\n * The header's client leaves. They receive ids, labels, flags and class strings only; every link and panel is\n * server-rendered and passed in as `children`. The leaves toggle `data-state`, `aria-expanded` and `inert` on those\n * server nodes, so opening a panel never re-renders its links. `inert` is added only after hydration: closed panels\n * are `visibility: hidden` in the server HTML, and inert content would break the pre-hydration hover fallback.\n */\nimport { usePathname } from 'next/navigation'\nimport { createContext, useContext, useEffect, useRef, useState, type ReactNode } from 'react'\nimport { useHeaderMetrics } from '../../navigation/use-header-metrics.js'\nimport { useNavigationMenu, type NavigationMenu } from '../../navigation/use-navigation-menu.js'\nimport { isCurrentSection } from './current-link.js'\nimport { HeaderModeContext } from './shell-context.js'\n\n/** The `<header>` root: measures the header (mode, height, compact) and shares its mode. */\nexport function HeaderRoot({\n variant,\n navAlign,\n compactAfterScroll,\n className,\n children,\n}: {\n readonly variant: string\n readonly navAlign: string\n readonly compactAfterScroll: boolean\n readonly className?: string | undefined\n readonly children: ReactNode\n}) {\n const ref = useRef<HTMLElement>(null)\n const { mode } = useHeaderMetrics(ref, { compactAfterScroll })\n return (\n <header ref={ref} data-bl=\"header\" data-variant={variant} data-nav-align={navAlign} className={className}>\n <HeaderModeContext value={mode}>{children}</HeaderModeContext>\n </header>\n )\n}\n\ninterface NavState {\n readonly menu: NavigationMenu\n readonly hydrated: boolean\n}\n\nconst NavContext = createContext<NavState | null>(null)\n\n/** The `<nav>` landmark and the menu state (F3 engine) for the items inside it. */\nexport function NavController({ label, className, children }: { readonly label: string; readonly className?: string | undefined; readonly children: ReactNode }) {\n const navRef = useRef<HTMLElement>(null)\n const pathname = usePathname()\n const mode = useContext(HeaderModeContext)\n const menu = useNavigationMenu(navRef, `${pathname}|${mode}`)\n const [hydrated, setHydrated] = useState(false)\n useEffect(() => setHydrated(true), [])\n return (\n <nav ref={navRef} aria-label={label} data-slot=\"nav\" className={className}>\n <NavContext value={{ menu, hydrated }}>{children}</NavContext>\n </nav>\n )\n}\n\n/**\n * One top-level item. `data-current` marks the current section: the page is the item's hub or one of its active\n * paths (or below them), or one of its panel links is the current page.\n */\nexport function NavItem({\n menuId,\n paths,\n className,\n children,\n}: {\n /** Set for an item with a panel. */\n readonly menuId?: string\n readonly paths: readonly string[]\n readonly className?: string | undefined\n readonly children: ReactNode\n}) {\n const ref = useRef<HTMLLIElement>(null)\n const pathname = usePathname()\n const nav = useContext(NavContext)\n const [panelLinkCurrent, setPanelLinkCurrent] = useState(false)\n useEffect(() => {\n setPanelLinkCurrent(ref.current?.querySelector('[data-slot=\"panel\"] [aria-current=\"page\"]') != null)\n }, [pathname])\n const current = panelLinkCurrent || isCurrentSection(pathname, paths)\n const open = menuId !== undefined && nav?.menu.openId === menuId\n return (\n <li\n ref={ref}\n data-slot=\"item\"\n data-has-panel={menuId !== undefined ? 'true' : undefined}\n data-state={menuId !== undefined ? (open ? 'open' : 'closed') : undefined}\n data-current={current ? 'true' : undefined}\n className={className}\n {...(menuId !== undefined && nav ? nav.menu.itemHandlers(menuId) : {})}\n >\n {children}\n </li>\n )\n}\n\n/** The disclosure button beside an item's hub link, named \"{label} menu\". */\nexport function NavTrigger({\n menuId,\n panelId,\n label,\n className,\n children,\n}: {\n readonly menuId: string\n readonly panelId: string\n readonly label: string\n readonly className?: string | undefined\n readonly children: ReactNode\n}) {\n const nav = useContext(NavContext)\n return (\n <button\n type=\"button\"\n data-slot=\"trigger\"\n data-menu-id={menuId}\n aria-expanded={nav?.menu.openId === menuId}\n aria-controls={panelId}\n aria-label={`${label} menu`}\n className={className}\n {...nav?.menu.triggerHandlers(menuId)}\n >\n {children}\n </button>\n )\n}\n\n/** The panel box. Its links are the server-rendered children; the panel only changes state. */\nexport function NavPanel({\n menuId,\n panelId,\n variant,\n columns,\n className,\n children,\n}: {\n readonly menuId: string\n readonly panelId: string\n readonly variant: string\n readonly columns?: number | undefined\n readonly className?: string | undefined\n readonly children: ReactNode\n}) {\n const nav = useContext(NavContext)\n const open = nav?.menu.openId === menuId\n return (\n <div\n id={panelId}\n data-slot=\"panel\"\n data-menu-id={menuId}\n data-variant={variant}\n data-columns={columns}\n data-state={open ? 'open' : 'closed'}\n inert={Boolean(nav?.hydrated) && !open}\n className={className}\n {...nav?.menu.panelHandlers(menuId)}\n >\n {children}\n </div>\n )\n}\n"]}
@@ -0,0 +1,6 @@
1
+ export { SITE_HEADER_VARIANTS, SiteHeader, type SiteHeaderLayout, type SiteHeaderProps, type SiteHeaderSkin, type SiteHeaderSlot, type SiteHeaderVariant, } from './site-header.js';
2
+ export { MOBILE_DRAWER_VARIANTS, MobileDrawer, type MobileDrawerLayout, type MobileDrawerProps, type MobileDrawerSkin, type MobileDrawerSlot, type MobileDrawerVariant, type ShellQuote, } from './mobile-drawer.js';
3
+ export { UtilityBar, type UtilityBarLayout, type UtilityBarProps, type UtilityBarSkin, type UtilityBarSlot, type UtilityLicence, type UtilityRating, } from './utility-bar.js';
4
+ export { MOBILE_CALL_BAR_VARIANTS, MobileCallBar, type MobileCallBarProps, type MobileCallBarSkin, type MobileCallBarSlot, type MobileCallBarVariant, } from './mobile-call-bar.js';
5
+ export { BACK_TO_TOP_OFFSETS, BackToTop, type BackToTopLayout, type BackToTopProps, type BackToTopSkin, type BackToTopSlot } from './back-to-top.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,wBAAwB,EACxB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,6 @@
1
+ export { SITE_HEADER_VARIANTS, SiteHeader, } from './site-header.js';
2
+ export { MOBILE_DRAWER_VARIANTS, MobileDrawer, } from './mobile-drawer.js';
3
+ export { UtilityBar, } from './utility-bar.js';
4
+ export { MOBILE_CALL_BAR_VARIANTS, MobileCallBar, } from './mobile-call-bar.js';
5
+ export { BACK_TO_TOP_OFFSETS, BackToTop } from './back-to-top.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,GAMX,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,sBAAsB,EACtB,YAAY,GAOb,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,UAAU,GAOX,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,wBAAwB,EACxB,aAAa,GAKd,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAqF,MAAM,kBAAkB,CAAA","sourcesContent":["export {\n SITE_HEADER_VARIANTS,\n SiteHeader,\n type SiteHeaderLayout,\n type SiteHeaderProps,\n type SiteHeaderSkin,\n type SiteHeaderSlot,\n type SiteHeaderVariant,\n} from './site-header.js'\nexport {\n MOBILE_DRAWER_VARIANTS,\n MobileDrawer,\n type MobileDrawerLayout,\n type MobileDrawerProps,\n type MobileDrawerSkin,\n type MobileDrawerSlot,\n type MobileDrawerVariant,\n type ShellQuote,\n} from './mobile-drawer.js'\nexport {\n UtilityBar,\n type UtilityBarLayout,\n type UtilityBarProps,\n type UtilityBarSkin,\n type UtilityBarSlot,\n type UtilityLicence,\n type UtilityRating,\n} from './utility-bar.js'\nexport {\n MOBILE_CALL_BAR_VARIANTS,\n MobileCallBar,\n type MobileCallBarProps,\n type MobileCallBarSkin,\n type MobileCallBarSlot,\n type MobileCallBarVariant,\n} from './mobile-call-bar.js'\nexport { BACK_TO_TOP_OFFSETS, BackToTop, type BackToTopLayout, type BackToTopProps, type BackToTopSkin, type BackToTopSlot } from './back-to-top.js'\n"]}
@@ -0,0 +1,16 @@
1
+ import type { SkinEntry } from '../skin.js';
2
+ import type { UiPhone } from '../types.js';
3
+ import type { ShellQuote } from './mobile-drawer.js';
4
+ export type MobileCallBarSlot = 'root' | 'call' | 'quote';
5
+ export declare const MOBILE_CALL_BAR_VARIANTS: readonly ["bar", "float"];
6
+ /** `bar`: full width; `float`: two pills at the end. */
7
+ export type MobileCallBarVariant = (typeof MOBILE_CALL_BAR_VARIANTS)[number];
8
+ export type MobileCallBarSkin = SkinEntry<MobileCallBarSlot, MobileCallBarVariant>;
9
+ export interface MobileCallBarProps extends MobileCallBarSkin {
10
+ readonly phone: UiPhone;
11
+ /** Words before the number, for example "Call". The button's name always includes the number. */
12
+ readonly phoneLabel?: string | undefined;
13
+ readonly quote: ShellQuote;
14
+ }
15
+ export declare function MobileCallBar({ phone, phoneLabel, quote, variant, classes }: MobileCallBarProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=mobile-call-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-call-bar.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/mobile-call-bar.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEpD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AACzD,eAAO,MAAM,wBAAwB,2BAA4B,CAAA;AACjE,wDAAwD;AACxD,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAA;AAC5E,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAA;AAElF,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,iGAAiG;IACjG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAe,EAAE,OAAO,EAAE,EAAE,kBAAkB,2CAOvG"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * F6: the phone call bar (server component). Call and quote always one tap away below 1024 px: it shows once the
4
+ * hero's own call and quote buttons (`data-bl-call-path`) have scrolled out, and hides over the footer, the drawer, a
5
+ * dialog, any call path and while a form field has focus. Call reports placement `fab`; the quote button sends
6
+ * `lead_cta_click` with placement `floating`. Render it once, after the page's `<main>`.
7
+ */
8
+ import { PhoneLink } from '../primitives/links.js';
9
+ import { QuoteButton } from '../primitives/quote-button.js';
10
+ import { CallBarController } from './call-bar-client.js';
11
+ export const MOBILE_CALL_BAR_VARIANTS = ['bar', 'float'];
12
+ export function MobileCallBar({ phone, phoneLabel, quote, variant = 'bar', classes }) {
13
+ return (_jsxs(CallBarController, { variant: variant, className: classes?.root, children: [_jsx(PhoneLink, { phone: phone, placement: "fab", label: phoneLabel, showIcon: true, variant: "button", classes: { root: classes?.call } }), _jsx(QuoteButton, { label: quote.label, href: quote.href, placement: "floating", ctaId: "quote-callbar", classes: { root: classes?.quote } })] }));
14
+ }
15
+ //# sourceMappingURL=mobile-call-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-call-bar.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/mobile-call-bar.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAG3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAIxD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAK,EAAE,OAAO,CAAU,CAAA;AAYjE,MAAM,UAAU,aAAa,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,OAAO,EAAsB;IACtG,OAAO,CACL,MAAC,iBAAiB,IAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,aAC3D,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAC,KAAK,EAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,QAAC,OAAO,EAAC,QAAQ,EAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAI,EAC1H,KAAC,WAAW,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAC,UAAU,EAAC,KAAK,EAAC,eAAe,EAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAI,IACjH,CACrB,CAAA;AACH,CAAC","sourcesContent":["/**\n * F6: the phone call bar (server component). Call and quote always one tap away below 1024 px: it shows once the\n * hero's own call and quote buttons (`data-bl-call-path`) have scrolled out, and hides over the footer, the drawer, a\n * dialog, any call path and while a form field has focus. Call reports placement `fab`; the quote button sends\n * `lead_cta_click` with placement `floating`. Render it once, after the page's `<main>`.\n */\nimport { PhoneLink } from '../primitives/links.js'\nimport { QuoteButton } from '../primitives/quote-button.js'\nimport type { SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\nimport { CallBarController } from './call-bar-client.js'\nimport type { ShellQuote } from './mobile-drawer.js'\n\nexport type MobileCallBarSlot = 'root' | 'call' | 'quote'\nexport const MOBILE_CALL_BAR_VARIANTS = ['bar', 'float'] as const\n/** `bar`: full width; `float`: two pills at the end. */\nexport type MobileCallBarVariant = (typeof MOBILE_CALL_BAR_VARIANTS)[number]\nexport type MobileCallBarSkin = SkinEntry<MobileCallBarSlot, MobileCallBarVariant>\n\nexport interface MobileCallBarProps extends MobileCallBarSkin {\n readonly phone: UiPhone\n /** Words before the number, for example \"Call\". The button's name always includes the number. */\n readonly phoneLabel?: string | undefined\n readonly quote: ShellQuote\n}\n\nexport function MobileCallBar({ phone, phoneLabel, quote, variant = 'bar', classes }: MobileCallBarProps) {\n return (\n <CallBarController variant={variant} className={classes?.root}>\n <PhoneLink phone={phone} placement=\"fab\" label={phoneLabel} showIcon variant=\"button\" classes={{ root: classes?.call }} />\n <QuoteButton label={quote.label} href={quote.href} placement=\"floating\" ctaId=\"quote-callbar\" classes={{ root: classes?.quote }} />\n </CallBarController>\n )\n}\n"]}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * F4: the phone and compact-band menu (server component). A modal dialog named "Menu", sliding in at
3
+ * `min(100%, 420px)`: the close button first, then the groups as accordions (one open at a time), the plain links,
4
+ * full-width Call and quote buttons, and the social links. Every link is in the server HTML. `SiteHeader` renders it;
5
+ * render it on its own only inside a recorded bespoke header.
6
+ */
7
+ import type { BrandlabNavigation } from '@brandlab-digital/site-core/navigation';
8
+ import type { ReactNode } from 'react';
9
+ import { type SkinEntry } from '../skin.js';
10
+ import type { UiPhone, UiSocial } from '../types.js';
11
+ export type MobileDrawerSlot = 'root' | 'menuButton' | 'menuLabel' | 'panel' | 'top' | 'close' | 'title' | 'logo' | 'nav' | 'group' | 'groupTrigger' | 'groupLinks' | 'groupLink' | 'links' | 'link' | 'actions' | 'call' | 'quote' | 'social' | 'socialLink';
12
+ export declare const MOBILE_DRAWER_VARIANTS: readonly ["side", "full"];
13
+ export type MobileDrawerVariant = (typeof MOBILE_DRAWER_VARIANTS)[number];
14
+ export interface MobileDrawerLayout {
15
+ /** The side the panel slides from (`side` variant). */
16
+ readonly side?: 'end' | 'start';
17
+ }
18
+ export type MobileDrawerSkin = SkinEntry<MobileDrawerSlot, MobileDrawerVariant, MobileDrawerLayout>;
19
+ /** The quote action. `href` is the quote form it falls back to without scripts, for example `/contact#quote`. */
20
+ export interface ShellQuote {
21
+ readonly label: string;
22
+ readonly href: string;
23
+ }
24
+ export interface MobileDrawerProps extends MobileDrawerSkin {
25
+ readonly navigation: BrandlabNavigation;
26
+ readonly phone: UiPhone;
27
+ /** Words before the number on the Call button, for example "Call". */
28
+ readonly phoneLabel?: string | undefined;
29
+ readonly quote: ShellQuote;
30
+ readonly socials?: readonly UiSocial[] | undefined;
31
+ /** An optional logo in the drawer's top bar (decorative there). */
32
+ readonly logo?: ReactNode;
33
+ /** Prefix for element ids; one per header on the page. */
34
+ readonly idPrefix?: string | undefined;
35
+ }
36
+ export declare function MobileDrawer({ navigation, phone, phoneLabel, quote, socials, logo, idPrefix, variant, layout, classes, }: MobileDrawerProps): import("react/jsx-runtime").JSX.Element;
37
+ //# sourceMappingURL=mobile-drawer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-drawer.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/mobile-drawer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAA4C,MAAM,wCAAwC,CAAA;AAC1H,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAKpD,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,YAAY,GACZ,WAAW,GACX,OAAO,GACP,KAAK,GACL,OAAO,GACP,OAAO,GACP,MAAM,GACN,KAAK,GACL,OAAO,GACP,cAAc,GACd,YAAY,GACZ,WAAW,GACX,OAAO,GACP,MAAM,GACN,SAAS,GACT,MAAM,GACN,OAAO,GACP,QAAQ,GACR,YAAY,CAAA;AAChB,eAAO,MAAM,sBAAsB,2BAA4B,CAAA;AAC/D,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AACzE,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAA;CAChC;AACD,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,kBAAkB,CAAC,CAAA;AAEnG,iHAAiH;AACjH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAA;IACvC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAA;IAClD,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,KAAK,EACL,UAAU,EACV,KAAK,EACL,OAAY,EACZ,IAAI,EACJ,QAAsB,EACtB,OAAgB,EAChB,MAAM,EACN,OAAO,GACR,EAAE,iBAAiB,2CAwEnB"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Icon } from '../icons.js';
3
+ import { PhoneLink } from '../primitives/links.js';
4
+ import { QuoteButton } from '../primitives/quote-button.js';
5
+ import { slot } from '../skin.js';
6
+ import { CurrentLink } from './current-link.js';
7
+ import { DrawerController } from './drawer-client.js';
8
+ import { SocialLinks } from './social-links.js';
9
+ export const MOBILE_DRAWER_VARIANTS = ['side', 'full'];
10
+ export function MobileDrawer({ navigation, phone, phoneLabel, quote, socials = [], logo, idPrefix = 'bl-header', variant = 'side', layout, classes, }) {
11
+ const id = `${idPrefix}-drawer`;
12
+ const groups = navigation.items.filter((item) => item.kind === 'menu');
13
+ const links = navigation.items.filter((item) => item.kind === 'link');
14
+ return (_jsxs(DrawerController, { id: id, variant: variant, side: layout?.side ?? 'end', classes: {
15
+ root: classes?.root,
16
+ menuButton: classes?.menuButton,
17
+ menuLabel: classes?.menuLabel,
18
+ panel: classes?.panel,
19
+ top: classes?.top,
20
+ close: classes?.close,
21
+ title: classes?.title,
22
+ logo: classes?.logo,
23
+ }, logo: logo, menuIcon: _jsx(Icon, { name: "menu" }), closeIcon: _jsx(Icon, { name: "close" }), children: [_jsxs("nav", { "aria-label": "Main", ...slot(classes, 'nav'), children: [groups.map((group) => (_jsxs("details", { name: `${id}-groups`, ...slot(classes, 'group'), children: [_jsxs("summary", { ...slot(classes, 'groupTrigger'), children: [_jsx("span", { children: group.label }), _jsx(Icon, { name: "chevron" })] }), _jsxs("ul", { ...slot(classes, 'groupLinks'), children: [_jsx("li", { children: _jsx(CurrentLink, { href: group.href, slot: "groupLink", prefetch: false, hub: true, className: classes?.groupLink, children: group.hubLabel }) }), group.featured && !group.links.some((link) => link.href === group.featured?.href) ? (_jsx("li", { children: _jsx(CurrentLink, { href: group.featured.href, slot: "groupLink", prefetch: false, className: classes?.groupLink, children: group.featured.label }) })) : null, group.links.map((link) => (_jsx("li", { children: _jsx(CurrentLink, { href: link.href, slot: "groupLink", prefetch: false, className: classes?.groupLink, children: link.label }) }, link.href)))] })] }, group.id))), links.length > 0 ? (_jsx("ul", { ...slot(classes, 'links'), children: links.map((link) => (_jsx("li", { children: _jsx(CurrentLink, { href: link.href, slot: "link", prefetch: false, className: classes?.link, children: link.label }) }, link.id))) })) : null] }), _jsxs("div", { ...slot(classes, 'actions'), children: [_jsx(PhoneLink, { phone: phone, placement: "header", label: phoneLabel, showIcon: true, variant: "button", classes: { root: classes?.call } }), _jsx(QuoteButton, { label: quote.label, href: quote.href, placement: "navigation", ctaId: "quote-menu", classes: { root: classes?.quote } })] }), _jsx(SocialLinks, { socials: socials, slotName: "social", className: classes?.social, linkClassName: classes?.socialLink })] }));
24
+ }
25
+ //# sourceMappingURL=mobile-drawer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-drawer.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/mobile-drawer.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * F4: the phone and compact-band menu (server component). A modal dialog named \"Menu\", sliding in at\n * `min(100%, 420px)`: the close button first, then the groups as accordions (one open at a time), the plain links,\n * full-width Call and quote buttons, and the social links. Every link is in the server HTML. `SiteHeader` renders it;\n * render it on its own only inside a recorded bespoke header.\n */\nimport type { BrandlabNavigation, BrandlabNavLinkItem, BrandlabNavMenuItem } from '@brandlab-digital/site-core/navigation'\nimport type { ReactNode } from 'react'\nimport { Icon } from '../icons.js'\nimport { PhoneLink } from '../primitives/links.js'\nimport { QuoteButton } from '../primitives/quote-button.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone, UiSocial } from '../types.js'\nimport { CurrentLink } from './current-link.js'\nimport { DrawerController } from './drawer-client.js'\nimport { SocialLinks } from './social-links.js'\n\nexport type MobileDrawerSlot =\n | 'root'\n | 'menuButton'\n | 'menuLabel'\n | 'panel'\n | 'top'\n | 'close'\n | 'title'\n | 'logo'\n | 'nav'\n | 'group'\n | 'groupTrigger'\n | 'groupLinks'\n | 'groupLink'\n | 'links'\n | 'link'\n | 'actions'\n | 'call'\n | 'quote'\n | 'social'\n | 'socialLink'\nexport const MOBILE_DRAWER_VARIANTS = ['side', 'full'] as const\nexport type MobileDrawerVariant = (typeof MOBILE_DRAWER_VARIANTS)[number]\nexport interface MobileDrawerLayout {\n /** The side the panel slides from (`side` variant). */\n readonly side?: 'end' | 'start'\n}\nexport type MobileDrawerSkin = SkinEntry<MobileDrawerSlot, MobileDrawerVariant, MobileDrawerLayout>\n\n/** The quote action. `href` is the quote form it falls back to without scripts, for example `/contact#quote`. */\nexport interface ShellQuote {\n readonly label: string\n readonly href: string\n}\n\nexport interface MobileDrawerProps extends MobileDrawerSkin {\n readonly navigation: BrandlabNavigation\n readonly phone: UiPhone\n /** Words before the number on the Call button, for example \"Call\". */\n readonly phoneLabel?: string | undefined\n readonly quote: ShellQuote\n readonly socials?: readonly UiSocial[] | undefined\n /** An optional logo in the drawer's top bar (decorative there). */\n readonly logo?: ReactNode\n /** Prefix for element ids; one per header on the page. */\n readonly idPrefix?: string | undefined\n}\n\nexport function MobileDrawer({\n navigation,\n phone,\n phoneLabel,\n quote,\n socials = [],\n logo,\n idPrefix = 'bl-header',\n variant = 'side',\n layout,\n classes,\n}: MobileDrawerProps) {\n const id = `${idPrefix}-drawer`\n const groups = navigation.items.filter((item): item is BrandlabNavMenuItem => item.kind === 'menu')\n const links = navigation.items.filter((item): item is BrandlabNavLinkItem => item.kind === 'link')\n return (\n <DrawerController\n id={id}\n variant={variant}\n side={layout?.side ?? 'end'}\n classes={{\n root: classes?.root,\n menuButton: classes?.menuButton,\n menuLabel: classes?.menuLabel,\n panel: classes?.panel,\n top: classes?.top,\n close: classes?.close,\n title: classes?.title,\n logo: classes?.logo,\n }}\n logo={logo}\n menuIcon={<Icon name=\"menu\" />}\n closeIcon={<Icon name=\"close\" />}\n >\n <nav aria-label=\"Main\" {...slot(classes, 'nav')}>\n {groups.map((group) => (\n <details key={group.id} name={`${id}-groups`} {...slot(classes, 'group')}>\n <summary {...slot(classes, 'groupTrigger')}>\n <span>{group.label}</span>\n <Icon name=\"chevron\" />\n </summary>\n <ul {...slot(classes, 'groupLinks')}>\n <li>\n <CurrentLink href={group.href} slot=\"groupLink\" prefetch={false} hub className={classes?.groupLink}>\n {group.hubLabel}\n </CurrentLink>\n </li>\n {group.featured && !group.links.some((link) => link.href === group.featured?.href) ? (\n <li>\n <CurrentLink href={group.featured.href} slot=\"groupLink\" prefetch={false} className={classes?.groupLink}>\n {group.featured.label}\n </CurrentLink>\n </li>\n ) : null}\n {group.links.map((link) => (\n <li key={link.href}>\n <CurrentLink href={link.href} slot=\"groupLink\" prefetch={false} className={classes?.groupLink}>\n {link.label}\n </CurrentLink>\n </li>\n ))}\n </ul>\n </details>\n ))}\n {links.length > 0 ? (\n <ul {...slot(classes, 'links')}>\n {links.map((link) => (\n <li key={link.id}>\n <CurrentLink href={link.href} slot=\"link\" prefetch={false} className={classes?.link}>\n {link.label}\n </CurrentLink>\n </li>\n ))}\n </ul>\n ) : null}\n </nav>\n <div {...slot(classes, 'actions')}>\n <PhoneLink phone={phone} placement=\"header\" label={phoneLabel} showIcon variant=\"button\" classes={{ root: classes?.call }} />\n <QuoteButton label={quote.label} href={quote.href} placement=\"navigation\" ctaId=\"quote-menu\" classes={{ root: classes?.quote }} />\n </div>\n <SocialLinks socials={socials} slotName=\"social\" className={classes?.social} linkClassName={classes?.socialLink} />\n </DrawerController>\n )\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { HeaderMode } from '../../navigation/constants.js';
2
+ export declare const HeaderModeContext: import("react").Context<HeaderMode | null>;
3
+ //# sourceMappingURL=shell-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-context.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/shell-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAE/D,eAAO,MAAM,iBAAiB,4CAAyC,CAAA"}
@@ -0,0 +1,5 @@
1
+ 'use client';
2
+ /** The header's measured mode, shared by the header root with the menu and the drawer (both reset when it changes). */
3
+ import { createContext } from 'react';
4
+ export const HeaderModeContext = createContext(null);
5
+ //# sourceMappingURL=shell-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-context.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/shell-context.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,uHAAuH;AACvH,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAGrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAoB,IAAI,CAAC,CAAA","sourcesContent":["'use client'\n\n/** The header's measured mode, shared by the header root with the menu and the drawer (both reset when it changes). */\nimport { createContext } from 'react'\nimport type { HeaderMode } from '../../navigation/constants.js'\n\nexport const HeaderModeContext = createContext<HeaderMode | null>(null)\n"]}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * F2: the header shell (server component). The same structure on every site: the skip link, the optional utility
3
+ * bar, then a sticky, solid `<header>` holding the logo, the menu, the phone and the quote button. Layout follows the
4
+ * header's own width (container queries): from 1280 px the full menu; from 1024 to 1279 px a compact band with the
5
+ * phone and its number, the quote button and a Menu button; below 1024 px the logo, a 44 px call button and a 44 px
6
+ * Menu button. Every menu, hub and panel link is an `<a href>` in the server HTML (F3); client leaves only change
7
+ * state.
8
+ */
9
+ import type { BrandlabNavigation } from '@brandlab-digital/site-core/navigation';
10
+ import type { ReactNode } from 'react';
11
+ import { type SkinEntry } from '../skin.js';
12
+ import type { UiPhone, UiSocial } from '../types.js';
13
+ import { type MobileDrawerSkin, type ShellQuote } from './mobile-drawer.js';
14
+ export type SiteHeaderSlot = 'skip' | 'root' | 'bar' | 'inner' | 'logo' | 'nav' | 'list' | 'item' | 'itemRow' | 'link' | 'trigger' | 'panel' | 'panelBody' | 'panelList' | 'panelGroup' | 'panelHeading' | 'panelLink' | 'panelLabel' | 'panelText' | 'featured' | 'featuredMedia' | 'featuredLabel' | 'featuredText' | 'actions' | 'phone' | 'phoneIcon' | 'phoneLabel' | 'phoneNumber' | 'quote' | 'quoteLabel' | 'quoteIcon' | 'menuButton' | 'menuLabel';
15
+ export declare const SITE_HEADER_VARIANTS: readonly ["standard", "call-first"];
16
+ /**
17
+ * `call-first` (recorded exceptions, v1 §9.10): the phone is the primary action (a button with its number at every
18
+ * width); the quote button still follows it, as on `standard`.
19
+ */
20
+ export type SiteHeaderVariant = (typeof SITE_HEADER_VARIANTS)[number];
21
+ export interface SiteHeaderLayout {
22
+ /** Where the menu sits between the logo and the actions. */
23
+ readonly navAlign?: 'center' | 'end';
24
+ /** Compact the header (`data-compact="true"`) once the page has scrolled 80 px. It never hides. */
25
+ readonly compactAfterScroll?: boolean;
26
+ }
27
+ export type SiteHeaderSkin = SkinEntry<SiteHeaderSlot, SiteHeaderVariant, SiteHeaderLayout>;
28
+ export interface SiteHeaderProps extends SiteHeaderSkin {
29
+ readonly navigation: BrandlabNavigation;
30
+ /** The logo link's accessible name. */
31
+ readonly brandName: string;
32
+ readonly homeHref: string;
33
+ readonly logo: ReactNode;
34
+ /** From the derived business facts, never typed by hand. */
35
+ readonly phone: UiPhone;
36
+ /** The small line above the number, for example "Call us". Also leads the drawer's Call button. */
37
+ readonly phoneLabel?: string | undefined;
38
+ readonly quote: ShellQuote;
39
+ readonly socials?: readonly UiSocial[] | undefined;
40
+ /** The site's skip-link text, for example "Skip to main content". It targets `#main`. */
41
+ readonly skipLabel: string;
42
+ /** The optional utility bar (`<UtilityBar>`), placed between the skip link and the header. */
43
+ readonly utility?: ReactNode;
44
+ /** The site's `mobileDrawer` skin entry. */
45
+ readonly drawer?: MobileDrawerSkin | undefined;
46
+ /** An optional logo for the drawer's top bar. */
47
+ readonly drawerLogo?: ReactNode;
48
+ /** Prefix for element ids; one per header on the page. */
49
+ readonly idPrefix?: string | undefined;
50
+ }
51
+ export declare function SiteHeader({ navigation, brandName, homeHref, logo, phone, phoneLabel, quote, socials, skipLabel, utility, drawer, drawerLogo, idPrefix, variant, layout, classes, }: SiteHeaderProps): import("react/jsx-runtime").JSX.Element;
52
+ //# sourceMappingURL=site-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-header.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/site-header.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAA4C,MAAM,wCAAwC,CAAA;AAG1H,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,OAAO,EAAY,KAAK,SAAS,EAAoB,MAAM,YAAY,CAAA;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,EAAgB,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAEzF,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,MAAM,GACN,KAAK,GACL,OAAO,GACP,MAAM,GACN,KAAK,GACL,MAAM,GACN,MAAM,GACN,SAAS,GACT,MAAM,GACN,SAAS,GACT,OAAO,GACP,WAAW,GACX,WAAW,GACX,YAAY,GACZ,cAAc,GACd,WAAW,GACX,YAAY,GACZ,WAAW,GACX,UAAU,GACV,eAAe,GACf,eAAe,GACf,cAAc,GACd,SAAS,GACT,OAAO,GACP,WAAW,GACX,YAAY,GACZ,aAAa,GACb,OAAO,GACP,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,WAAW,CAAA;AACf,eAAO,MAAM,oBAAoB,qCAAsC,CAAA;AACvE;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AACrE,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IACpC,mGAAmG;IACnG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;CACtC;AACD,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,CAAA;AAE3F,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAA;IACvC,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,mGAAmG;IACnG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAA;IAClD,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAA;IAC9C,iDAAiD;IACjD,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;IAC/B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED,wBAAgB,UAAU,CAAC,EACzB,UAAU,EACV,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,UAAU,EACV,KAAK,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,MAAM,EACN,UAAU,EACV,QAAsB,EACtB,OAAoB,EACpB,MAAM,EACN,OAAO,GACR,EAAE,eAAe,2CAoEjB"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import Image from 'next/image';
3
+ import Link from 'next/link';
4
+ import { SkipLink } from '../../ui.js';
5
+ import { MAIN_CONTENT_ID } from '../../navigation/constants.js';
6
+ import { Icon } from '../icons.js';
7
+ import { PhoneLink } from '../primitives/links.js';
8
+ import { QuoteButton } from '../primitives/quote-button.js';
9
+ import { cx, slot } from '../skin.js';
10
+ import { CurrentLink } from './current-link.js';
11
+ import { HeaderRoot, NavController, NavItem, NavPanel, NavTrigger } from './header-client.js';
12
+ import { MobileDrawer } from './mobile-drawer.js';
13
+ export const SITE_HEADER_VARIANTS = ['standard', 'call-first'];
14
+ export function SiteHeader({ navigation, brandName, homeHref, logo, phone, phoneLabel, quote, socials, skipLabel, utility, drawer, drawerLogo, idPrefix = 'bl-header', variant = 'standard', layout, classes, }) {
15
+ const callFirst = variant === 'call-first';
16
+ return (_jsxs(_Fragment, { children: [_jsx(SkipLink, { targetId: MAIN_CONTENT_ID, "data-bl": "skip", className: classes?.skip, children: skipLabel }), utility, _jsx(HeaderRoot, { variant: variant, navAlign: layout?.navAlign ?? 'center', compactAfterScroll: layout?.compactAfterScroll ?? false, className: classes?.root, children: _jsx("div", { ...slot(classes, 'bar'), children: _jsxs("div", { ...slot(classes, 'inner'), children: [_jsx(Link, { href: homeHref, "aria-label": brandName, ...slot(classes, 'logo'), children: logo }), _jsx(NavController, { label: "Main", className: classes?.nav, children: _jsx("ul", { ...slot(classes, 'list'), children: navigation.items.map((item) => item.kind === 'link' ? (_jsx(LinkItem, { item: item, classes: classes }, item.id)) : (_jsx(MenuItem, { item: item, panelId: `${idPrefix}-panel-${item.id}`, classes: classes }, item.id))) }) }), _jsxs("div", { ...slot(classes, 'actions'), children: [_jsx(PhoneLink, { phone: phone, placement: "header", label: phoneLabel, showIcon: true, variant: callFirst ? 'button' : 'text', classes: { root: classes?.phone, icon: classes?.phoneIcon, label: classes?.phoneLabel, number: classes?.phoneNumber } }), _jsx(QuoteButton, { label: quote.label, href: quote.href, placement: "header", ctaId: "quote-header", classes: { root: classes?.quote, label: classes?.quoteLabel, icon: classes?.quoteIcon } }), _jsx(MobileDrawer, { ...drawer, classes: {
17
+ ...drawer?.classes,
18
+ menuButton: cx(drawer?.classes?.menuButton, classes?.menuButton),
19
+ menuLabel: cx(drawer?.classes?.menuLabel, classes?.menuLabel),
20
+ }, navigation: navigation, phone: phone, phoneLabel: phoneLabel, quote: quote, socials: socials, logo: drawerLogo, idPrefix: idPrefix })] })] }) }) })] }));
21
+ }
22
+ function LinkItem({ item, classes }) {
23
+ return (_jsx(NavItem, { paths: [item.href, ...(item.activePaths ?? [])], className: classes?.item, children: _jsx(CurrentLink, { href: item.href, slot: "link", className: classes?.link, children: item.label }) }));
24
+ }
25
+ function MenuItem({ item, panelId, classes }) {
26
+ const groups = item.panel === 'columns' && item.groups && item.groups.length > 0 ? item.groups : undefined;
27
+ // A columns panel never drops a link: links outside every group follow in a last group without a heading.
28
+ const grouped = new Set(groups?.flatMap((group) => group.links.map((link) => link.href)));
29
+ const ungrouped = groups ? item.links.filter((link) => !grouped.has(link.href)) : [];
30
+ const columnCount = groups ? groups.length + (ungrouped.length > 0 ? 1 : 0) : 0;
31
+ return (_jsxs(NavItem, { menuId: item.id, paths: [item.href, ...(item.activePaths ?? [])], className: classes?.item, children: [_jsxs("span", { ...slot(classes, 'itemRow'), children: [_jsx(CurrentLink, { href: item.href, slot: "link", className: classes?.link, children: item.label }), _jsx(NavTrigger, { menuId: item.id, panelId: panelId, label: item.label, className: classes?.trigger, children: _jsx(Icon, { name: "chevron" }) })] }), _jsx(NavPanel, { menuId: item.id, panelId: panelId, variant: item.panel, columns: groups ? Math.min(3, Math.max(2, columnCount)) : undefined, className: classes?.panel, children: _jsxs("div", { ...slot(classes, 'panelBody'), children: [item.panel === 'featured' && item.featured ? (_jsxs(CurrentLink, { href: item.featured.href, slot: "featured", prefetch: false, className: classes?.featured, children: [_jsx("span", { ...slot(classes, 'featuredMedia'), children: _jsx(Image, { src: item.featured.image.src, alt: item.featured.image.alt, width: item.featured.image.width, height: item.featured.image.height, sizes: "240px" }) }), _jsx("span", { ...slot(classes, 'featuredLabel'), children: item.featured.label }), _jsx("span", { ...slot(classes, 'featuredText'), children: item.featured.description })] })) : null, _jsxs("ul", { ...slot(classes, 'panelList'), children: [_jsx("li", { children: _jsxs(CurrentLink, { href: item.href, slot: "panelLink", hub: true, prefetch: false, className: classes?.panelLink, children: [_jsx("span", { ...slot(classes, 'panelLabel'), children: item.hubLabel }), _jsx(Icon, { name: "arrow" })] }) }), groups ? null : item.links.map((link) => _jsx(PanelLink, { link: link, classes: classes }, link.href))] }), groups?.map((group) => (_jsxs("div", { ...slot(classes, 'panelGroup'), children: [_jsx("p", { ...slot(classes, 'panelHeading'), children: group.heading }), _jsx("ul", { ...slot(classes, 'panelList'), children: group.links.map((link) => (_jsx(PanelLink, { link: link, classes: classes }, link.href))) })] }, group.heading))), ungrouped.length > 0 ? (_jsx("div", { ...slot(classes, 'panelGroup'), children: _jsx("ul", { ...slot(classes, 'panelList'), children: ungrouped.map((link) => (_jsx(PanelLink, { link: link, classes: classes }, link.href))) }) })) : null] }) })] }));
32
+ }
33
+ function PanelLink({ link, classes }) {
34
+ return (_jsx("li", { children: _jsxs(CurrentLink, { href: link.href, slot: "panelLink", prefetch: false, className: classes?.panelLink, children: [_jsx("span", { ...slot(classes, 'panelLabel'), children: link.label }), link.description ? _jsx("span", { ...slot(classes, 'panelText'), children: link.description }) : null] }) }));
35
+ }
36
+ //# sourceMappingURL=site-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-header.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/site-header.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * F2: the header shell (server component). The same structure on every site: the skip link, the optional utility\n * bar, then a sticky, solid `<header>` holding the logo, the menu, the phone and the quote button. Layout follows the\n * header's own width (container queries): from 1280 px the full menu; from 1024 to 1279 px a compact band with the\n * phone and its number, the quote button and a Menu button; below 1024 px the logo, a 44 px call button and a 44 px\n * Menu button. Every menu, hub and panel link is an `<a href>` in the server HTML (F3); client leaves only change\n * state.\n */\nimport type { BrandlabNavigation, BrandlabNavLinkItem, BrandlabNavMenuItem } from '@brandlab-digital/site-core/navigation'\nimport Image from 'next/image'\nimport Link from 'next/link'\nimport type { ReactNode } from 'react'\nimport { SkipLink } from '../../ui.js'\nimport { MAIN_CONTENT_ID } from '../../navigation/constants.js'\nimport { Icon } from '../icons.js'\nimport { PhoneLink } from '../primitives/links.js'\nimport { QuoteButton } from '../primitives/quote-button.js'\nimport { cx, slot, type SkinEntry, type SlotClasses } from '../skin.js'\nimport type { UiPhone, UiSocial } from '../types.js'\nimport { CurrentLink } from './current-link.js'\nimport { HeaderRoot, NavController, NavItem, NavPanel, NavTrigger } from './header-client.js'\nimport { MobileDrawer, type MobileDrawerSkin, type ShellQuote } from './mobile-drawer.js'\n\nexport type SiteHeaderSlot =\n | 'skip'\n | 'root'\n | 'bar'\n | 'inner'\n | 'logo'\n | 'nav'\n | 'list'\n | 'item'\n | 'itemRow'\n | 'link'\n | 'trigger'\n | 'panel'\n | 'panelBody'\n | 'panelList'\n | 'panelGroup'\n | 'panelHeading'\n | 'panelLink'\n | 'panelLabel'\n | 'panelText'\n | 'featured'\n | 'featuredMedia'\n | 'featuredLabel'\n | 'featuredText'\n | 'actions'\n | 'phone'\n | 'phoneIcon'\n | 'phoneLabel'\n | 'phoneNumber'\n | 'quote'\n | 'quoteLabel'\n | 'quoteIcon'\n | 'menuButton'\n | 'menuLabel'\nexport const SITE_HEADER_VARIANTS = ['standard', 'call-first'] as const\n/**\n * `call-first` (recorded exceptions, v1 §9.10): the phone is the primary action (a button with its number at every\n * width); the quote button still follows it, as on `standard`.\n */\nexport type SiteHeaderVariant = (typeof SITE_HEADER_VARIANTS)[number]\nexport interface SiteHeaderLayout {\n /** Where the menu sits between the logo and the actions. */\n readonly navAlign?: 'center' | 'end'\n /** Compact the header (`data-compact=\"true\"`) once the page has scrolled 80 px. It never hides. */\n readonly compactAfterScroll?: boolean\n}\nexport type SiteHeaderSkin = SkinEntry<SiteHeaderSlot, SiteHeaderVariant, SiteHeaderLayout>\n\nexport interface SiteHeaderProps extends SiteHeaderSkin {\n readonly navigation: BrandlabNavigation\n /** The logo link's accessible name. */\n readonly brandName: string\n readonly homeHref: string\n readonly logo: ReactNode\n /** From the derived business facts, never typed by hand. */\n readonly phone: UiPhone\n /** The small line above the number, for example \"Call us\". Also leads the drawer's Call button. */\n readonly phoneLabel?: string | undefined\n readonly quote: ShellQuote\n readonly socials?: readonly UiSocial[] | undefined\n /** The site's skip-link text, for example \"Skip to main content\". It targets `#main`. */\n readonly skipLabel: string\n /** The optional utility bar (`<UtilityBar>`), placed between the skip link and the header. */\n readonly utility?: ReactNode\n /** The site's `mobileDrawer` skin entry. */\n readonly drawer?: MobileDrawerSkin | undefined\n /** An optional logo for the drawer's top bar. */\n readonly drawerLogo?: ReactNode\n /** Prefix for element ids; one per header on the page. */\n readonly idPrefix?: string | undefined\n}\n\nexport function SiteHeader({\n navigation,\n brandName,\n homeHref,\n logo,\n phone,\n phoneLabel,\n quote,\n socials,\n skipLabel,\n utility,\n drawer,\n drawerLogo,\n idPrefix = 'bl-header',\n variant = 'standard',\n layout,\n classes,\n}: SiteHeaderProps) {\n const callFirst = variant === 'call-first'\n return (\n <>\n <SkipLink targetId={MAIN_CONTENT_ID} data-bl=\"skip\" className={classes?.skip}>\n {skipLabel}\n </SkipLink>\n {utility}\n <HeaderRoot\n variant={variant}\n navAlign={layout?.navAlign ?? 'center'}\n compactAfterScroll={layout?.compactAfterScroll ?? false}\n className={classes?.root}\n >\n <div {...slot(classes, 'bar')}>\n <div {...slot(classes, 'inner')}>\n <Link href={homeHref} aria-label={brandName} {...slot(classes, 'logo')}>\n {logo}\n </Link>\n <NavController label=\"Main\" className={classes?.nav}>\n <ul {...slot(classes, 'list')}>\n {navigation.items.map((item) =>\n item.kind === 'link' ? (\n <LinkItem key={item.id} item={item} classes={classes} />\n ) : (\n <MenuItem key={item.id} item={item} panelId={`${idPrefix}-panel-${item.id}`} classes={classes} />\n ),\n )}\n </ul>\n </NavController>\n <div {...slot(classes, 'actions')}>\n {/* The phone sits beside the quote button with its icon on the left; its name is its visible text. */}\n <PhoneLink\n phone={phone}\n placement=\"header\"\n label={phoneLabel}\n showIcon\n variant={callFirst ? 'button' : 'text'}\n classes={{ root: classes?.phone, icon: classes?.phoneIcon, label: classes?.phoneLabel, number: classes?.phoneNumber }}\n />\n <QuoteButton\n label={quote.label}\n href={quote.href}\n placement=\"header\"\n ctaId=\"quote-header\"\n classes={{ root: classes?.quote, label: classes?.quoteLabel, icon: classes?.quoteIcon }}\n />\n <MobileDrawer\n {...drawer}\n classes={{\n ...drawer?.classes,\n menuButton: cx(drawer?.classes?.menuButton, classes?.menuButton),\n menuLabel: cx(drawer?.classes?.menuLabel, classes?.menuLabel),\n }}\n navigation={navigation}\n phone={phone}\n phoneLabel={phoneLabel}\n quote={quote}\n socials={socials}\n logo={drawerLogo}\n idPrefix={idPrefix}\n />\n </div>\n </div>\n </div>\n </HeaderRoot>\n </>\n )\n}\n\ntype Classes = SlotClasses<SiteHeaderSlot> | undefined\n\nfunction LinkItem({ item, classes }: { item: BrandlabNavLinkItem; classes: Classes }) {\n return (\n <NavItem paths={[item.href, ...(item.activePaths ?? [])]} className={classes?.item}>\n <CurrentLink href={item.href} slot=\"link\" className={classes?.link}>\n {item.label}\n </CurrentLink>\n </NavItem>\n )\n}\n\nfunction MenuItem({ item, panelId, classes }: { item: BrandlabNavMenuItem; panelId: string; classes: Classes }) {\n const groups = item.panel === 'columns' && item.groups && item.groups.length > 0 ? item.groups : undefined\n // A columns panel never drops a link: links outside every group follow in a last group without a heading.\n const grouped = new Set(groups?.flatMap((group) => group.links.map((link) => link.href)))\n const ungrouped = groups ? item.links.filter((link) => !grouped.has(link.href)) : []\n const columnCount = groups ? groups.length + (ungrouped.length > 0 ? 1 : 0) : 0\n return (\n <NavItem menuId={item.id} paths={[item.href, ...(item.activePaths ?? [])]} className={classes?.item}>\n <span {...slot(classes, 'itemRow')}>\n <CurrentLink href={item.href} slot=\"link\" className={classes?.link}>\n {item.label}\n </CurrentLink>\n <NavTrigger menuId={item.id} panelId={panelId} label={item.label} className={classes?.trigger}>\n <Icon name=\"chevron\" />\n </NavTrigger>\n </span>\n <NavPanel\n menuId={item.id}\n panelId={panelId}\n variant={item.panel}\n columns={groups ? Math.min(3, Math.max(2, columnCount)) : undefined}\n className={classes?.panel}\n >\n <div {...slot(classes, 'panelBody')}>\n {item.panel === 'featured' && item.featured ? (\n <CurrentLink href={item.featured.href} slot=\"featured\" prefetch={false} className={classes?.featured}>\n <span {...slot(classes, 'featuredMedia')}>\n <Image\n src={item.featured.image.src}\n alt={item.featured.image.alt}\n width={item.featured.image.width}\n height={item.featured.image.height}\n sizes=\"240px\"\n />\n </span>\n <span {...slot(classes, 'featuredLabel')}>{item.featured.label}</span>\n <span {...slot(classes, 'featuredText')}>{item.featured.description}</span>\n </CurrentLink>\n ) : null}\n {/* Every panel repeats its hub link first. */}\n <ul {...slot(classes, 'panelList')}>\n <li>\n <CurrentLink href={item.href} slot=\"panelLink\" hub prefetch={false} className={classes?.panelLink}>\n <span {...slot(classes, 'panelLabel')}>{item.hubLabel}</span>\n <Icon name=\"arrow\" />\n </CurrentLink>\n </li>\n {groups ? null : item.links.map((link) => <PanelLink key={link.href} link={link} classes={classes} />)}\n </ul>\n {groups?.map((group) => (\n <div key={group.heading} {...slot(classes, 'panelGroup')}>\n <p {...slot(classes, 'panelHeading')}>{group.heading}</p>\n <ul {...slot(classes, 'panelList')}>\n {group.links.map((link) => (\n <PanelLink key={link.href} link={link} classes={classes} />\n ))}\n </ul>\n </div>\n ))}\n {ungrouped.length > 0 ? (\n <div {...slot(classes, 'panelGroup')}>\n <ul {...slot(classes, 'panelList')}>\n {ungrouped.map((link) => (\n <PanelLink key={link.href} link={link} classes={classes} />\n ))}\n </ul>\n </div>\n ) : null}\n </div>\n </NavPanel>\n </NavItem>\n )\n}\n\nfunction PanelLink({ link, classes }: { link: BrandlabNavMenuItem['links'][number]; classes: Classes }) {\n return (\n <li>\n <CurrentLink href={link.href} slot=\"panelLink\" prefetch={false} className={classes?.panelLink}>\n <span {...slot(classes, 'panelLabel')}>{link.label}</span>\n {link.description ? <span {...slot(classes, 'panelText')}>{link.description}</span> : null}\n </CurrentLink>\n </li>\n )\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { UiSocial } from '../types.js';
2
+ export declare function SocialLinks({ socials, slotName, className, linkClassName, }: {
3
+ readonly socials: readonly UiSocial[];
4
+ readonly slotName: string;
5
+ readonly className?: string | undefined;
6
+ readonly linkClassName?: string | undefined;
7
+ }): import("react/jsx-runtime").JSX.Element | null;
8
+ //# sourceMappingURL=social-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social-links.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/social-links.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,SAAS,EACT,aAAa,GACd,EAAE;IACD,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAA;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5C,kDAqBA"}
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /** Social and Business Profile icon links, shared by the drawer and the utility bar. Each link is named by its data. */
3
+ import { SocialIcon } from '../icons.js';
4
+ export function SocialLinks({ socials, slotName, className, linkClassName, }) {
5
+ if (socials.length === 0)
6
+ return null;
7
+ return (_jsx("ul", { "data-slot": slotName, className: className, children: socials.map((social) => (_jsx("li", { children: _jsx("a", { href: social.href, target: "_blank", rel: "noopener noreferrer", "aria-label": social.label, "data-slot": "socialLink", "data-social": social.kind, className: linkClassName, children: _jsx(SocialIcon, { kind: social.kind }) }) }, social.href))) }));
8
+ }
9
+ //# sourceMappingURL=social-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social-links.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/social-links.tsx"],"names":[],"mappings":";AAAA,wHAAwH;AACxH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,UAAU,WAAW,CAAC,EAC1B,OAAO,EACP,QAAQ,EACR,SAAS,EACT,aAAa,GAMd;IACC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,OAAO,CACL,0BAAe,QAAQ,EAAE,SAAS,EAAE,SAAS,YAC1C,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,uBACE,YACE,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,qBAAqB,gBACb,MAAM,CAAC,KAAK,eACd,YAAY,iBACT,MAAM,CAAC,IAAI,EACxB,SAAS,EAAE,aAAa,YAExB,KAAC,UAAU,IAAC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAI,GAC/B,IAXG,MAAM,CAAC,IAAI,CAYf,CACN,CAAC,GACC,CACN,CAAA;AACH,CAAC","sourcesContent":["/** Social and Business Profile icon links, shared by the drawer and the utility bar. Each link is named by its data. */\nimport { SocialIcon } from '../icons.js'\nimport type { UiSocial } from '../types.js'\n\nexport function SocialLinks({\n socials,\n slotName,\n className,\n linkClassName,\n}: {\n readonly socials: readonly UiSocial[]\n readonly slotName: string\n readonly className?: string | undefined\n readonly linkClassName?: string | undefined\n}) {\n if (socials.length === 0) return null\n return (\n <ul data-slot={slotName} className={className}>\n {socials.map((social) => (\n <li key={social.href}>\n <a\n href={social.href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={social.label}\n data-slot=\"socialLink\"\n data-social={social.kind}\n className={linkClassName}\n >\n <SocialIcon kind={social.kind} />\n </a>\n </li>\n ))}\n </ul>\n )\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { type SkinEntry } from '../skin.js';
2
+ import type { UiSocial } from '../types.js';
3
+ export type UtilityBarSlot = 'root' | 'inner' | 'left' | 'right' | 'item' | 'rating' | 'licence' | 'social' | 'socialLink';
4
+ export interface UtilityBarLayout {
5
+ /** Socials on the left and the rating and licences on the right. */
6
+ readonly reverse?: boolean;
7
+ }
8
+ export type UtilityBarSkin = SkinEntry<UtilityBarSlot, never, UtilityBarLayout>;
9
+ /** The live rating, all from the Business Profile feed: never typed by hand (T4). */
10
+ export interface UtilityRating {
11
+ /** The feed's average rating, for the stars. */
12
+ readonly rating: number;
13
+ /** The Google link from the feed. */
14
+ readonly href: string;
15
+ /** The words beside the stars, built from the same feed values, for example "4.9 from 212 Google reviews". */
16
+ readonly text: string;
17
+ }
18
+ /** A licence line from the business facts, with the register link where there is one. */
19
+ export interface UtilityLicence {
20
+ readonly text: string;
21
+ readonly href?: string | undefined;
22
+ }
23
+ export interface UtilityBarProps extends UtilityBarSkin {
24
+ /** Null or absent when the feed has no rating: the chip is left out. */
25
+ readonly rating?: UtilityRating | null | undefined;
26
+ readonly licences?: readonly UtilityLicence[] | undefined;
27
+ readonly socials?: readonly UiSocial[] | undefined;
28
+ }
29
+ export declare function UtilityBar({ rating, licences, socials, layout, classes }: UtilityBarProps): import("react/jsx-runtime").JSX.Element | null;
30
+ //# sourceMappingURL=utility-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utility-bar.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/shell/utility-bar.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAG3C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAA;AAC1H,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAC3B;AACD,MAAM,MAAM,cAAc,GAAG,SAAS,CAAC,cAAc,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAA;AAE/E,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,qCAAqC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8GAA8G;IAC9G,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,yFAAyF;AACzF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC;AAED,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,wEAAwE;IACxE,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAA;IAClD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,CAAA;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,CAAA;CACnD;AAED,wBAAgB,UAAU,CAAC,EAAE,MAAM,EAAE,QAAa,EAAE,OAAY,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,eAAe,kDAqCnG"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * F5: the optional strip above the header (server component). The live rating chip and licence lines on one side,
4
+ * social and Business Profile links on the other. Never the phone, "based in", "Open 24/7" or a typed rating. It
5
+ * scrolls away with the page and is hidden below 768 px. Pass it to `SiteHeader` as `utility`.
6
+ */
7
+ import { RatingStars } from '../primitives/layout.js';
8
+ import { slot } from '../skin.js';
9
+ import { SocialLinks } from './social-links.js';
10
+ export function UtilityBar({ rating, licences = [], socials = [], layout, classes }) {
11
+ if (!rating && licences.length === 0 && socials.length === 0)
12
+ return null;
13
+ return (_jsx("div", { "data-bl": "utility", "data-reverse": layout?.reverse ? 'true' : undefined, className: classes?.root, children: _jsxs("div", { ...slot(classes, 'inner'), children: [rating || licences.length > 0 ? (_jsxs("ul", { ...slot(classes, 'left'), children: [rating ? (_jsx("li", { ...slot(classes, 'item'), children: _jsxs("a", { href: rating.href, target: "_blank", rel: "noopener noreferrer", "data-bl-source": "feed", ...slot(classes, 'rating'), children: [_jsx(RatingStars, { rating: rating.rating }), _jsx("span", { children: rating.text })] }) })) : null, licences.map((licence) => (_jsx("li", { ...slot(classes, 'item'), children: licence.href ? (_jsx("a", { href: licence.href, target: "_blank", rel: "noopener noreferrer", ...slot(classes, 'licence'), children: licence.text })) : (_jsx("span", { ...slot(classes, 'licence'), children: licence.text })) }, licence.text)))] })) : null, socials.length > 0 ? (_jsx("div", { ...slot(classes, 'right'), children: _jsx(SocialLinks, { socials: socials, slotName: "social", className: classes?.social, linkClassName: classes?.socialLink }) })) : null] }) }));
14
+ }
15
+ //# sourceMappingURL=utility-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utility-bar.js","sourceRoot":"","sources":["../../../src/ui-kit/shell/utility-bar.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAgC/C,MAAM,UAAU,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAmB;IAClG,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACzE,OAAO,CACL,yBAAa,SAAS,kBAAe,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,YACjG,kBAAS,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,aAC5B,MAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC/B,iBAAQ,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,aAC1B,MAAM,CAAC,CAAC,CAAC,CACR,gBAAQ,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,YAE3B,aAAG,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,oBAAgB,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,aAC/G,KAAC,WAAW,IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAI,EACtC,yBAAO,MAAM,CAAC,IAAI,GAAQ,IACxB,GACD,CACN,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACzB,gBAA2B,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,YAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CACd,YAAG,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,KAAK,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAC1F,OAAO,CAAC,IAAI,GACX,CACL,CAAC,CAAC,CAAC,CACF,kBAAU,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAAG,OAAO,CAAC,IAAI,GAAQ,CAC1D,IAPM,OAAO,CAAC,IAAI,CAQhB,CACN,CAAC,IACC,CACN,CAAC,CAAC,CAAC,IAAI,EACP,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CACpB,iBAAS,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,YAC7B,KAAC,WAAW,IAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAC,QAAQ,EAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,GAAI,GAC/G,CACP,CAAC,CAAC,CAAC,IAAI,IACJ,GACF,CACP,CAAA;AACH,CAAC","sourcesContent":["/**\n * F5: the optional strip above the header (server component). The live rating chip and licence lines on one side,\n * social and Business Profile links on the other. Never the phone, \"based in\", \"Open 24/7\" or a typed rating. It\n * scrolls away with the page and is hidden below 768 px. Pass it to `SiteHeader` as `utility`.\n */\nimport { RatingStars } from '../primitives/layout.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiSocial } from '../types.js'\nimport { SocialLinks } from './social-links.js'\n\nexport type UtilityBarSlot = 'root' | 'inner' | 'left' | 'right' | 'item' | 'rating' | 'licence' | 'social' | 'socialLink'\nexport interface UtilityBarLayout {\n /** Socials on the left and the rating and licences on the right. */\n readonly reverse?: boolean\n}\nexport type UtilityBarSkin = SkinEntry<UtilityBarSlot, never, UtilityBarLayout>\n\n/** The live rating, all from the Business Profile feed: never typed by hand (T4). */\nexport interface UtilityRating {\n /** The feed's average rating, for the stars. */\n readonly rating: number\n /** The Google link from the feed. */\n readonly href: string\n /** The words beside the stars, built from the same feed values, for example \"4.9 from 212 Google reviews\". */\n readonly text: string\n}\n\n/** A licence line from the business facts, with the register link where there is one. */\nexport interface UtilityLicence {\n readonly text: string\n readonly href?: string | undefined\n}\n\nexport interface UtilityBarProps extends UtilityBarSkin {\n /** Null or absent when the feed has no rating: the chip is left out. */\n readonly rating?: UtilityRating | null | undefined\n readonly licences?: readonly UtilityLicence[] | undefined\n readonly socials?: readonly UiSocial[] | undefined\n}\n\nexport function UtilityBar({ rating, licences = [], socials = [], layout, classes }: UtilityBarProps) {\n if (!rating && licences.length === 0 && socials.length === 0) return null\n return (\n <div data-bl=\"utility\" data-reverse={layout?.reverse ? 'true' : undefined} className={classes?.root}>\n <div {...slot(classes, 'inner')}>\n {rating || licences.length > 0 ? (\n <ul {...slot(classes, 'left')}>\n {rating ? (\n <li {...slot(classes, 'item')}>\n {/* A minimal chip; the shared RatingChip (sections) replaces it at integration. */}\n <a href={rating.href} target=\"_blank\" rel=\"noopener noreferrer\" data-bl-source=\"feed\" {...slot(classes, 'rating')}>\n <RatingStars rating={rating.rating} />\n <span>{rating.text}</span>\n </a>\n </li>\n ) : null}\n {licences.map((licence) => (\n <li key={licence.text} {...slot(classes, 'item')}>\n {licence.href ? (\n <a href={licence.href} target=\"_blank\" rel=\"noopener noreferrer\" {...slot(classes, 'licence')}>\n {licence.text}\n </a>\n ) : (\n <span {...slot(classes, 'licence')}>{licence.text}</span>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n {socials.length > 0 ? (\n <div {...slot(classes, 'right')}>\n <SocialLinks socials={socials} slotName=\"social\" className={classes?.social} linkClassName={classes?.socialLink} />\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"]}