@brandlab-digital/site-next 3.15.1 → 3.16.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 (48) hide show
  1. package/dist/navigation/use-sticky-call-bar.d.ts +6 -1
  2. package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -1
  3. package/dist/navigation/use-sticky-call-bar.js +9 -4
  4. package/dist/navigation/use-sticky-call-bar.js.map +1 -1
  5. package/dist/ui-kit/brandlab-skin.d.ts +2 -0
  6. package/dist/ui-kit/brandlab-skin.d.ts.map +1 -1
  7. package/dist/ui-kit/brandlab-skin.js.map +1 -1
  8. package/dist/ui-kit/repeated-slots.d.ts +1 -1
  9. package/dist/ui-kit/repeated-slots.js +1 -1
  10. package/dist/ui-kit/repeated-slots.js.map +1 -1
  11. package/dist/ui-kit/sections/cta-band.d.ts +10 -2
  12. package/dist/ui-kit/sections/cta-band.d.ts.map +1 -1
  13. package/dist/ui-kit/sections/cta-band.js +2 -2
  14. package/dist/ui-kit/sections/cta-band.js.map +1 -1
  15. package/dist/ui-kit/sections/hero.d.ts +43 -2
  16. package/dist/ui-kit/sections/hero.d.ts.map +1 -1
  17. package/dist/ui-kit/sections/hero.js +86 -3
  18. package/dist/ui-kit/sections/hero.js.map +1 -1
  19. package/dist/ui-kit/sections/index.d.ts +3 -2
  20. package/dist/ui-kit/sections/index.d.ts.map +1 -1
  21. package/dist/ui-kit/sections/index.js +3 -2
  22. package/dist/ui-kit/sections/index.js.map +1 -1
  23. package/dist/ui-kit/sections/proof-strip.d.ts +7 -1
  24. package/dist/ui-kit/sections/proof-strip.d.ts.map +1 -1
  25. package/dist/ui-kit/sections/proof-strip.js +6 -2
  26. package/dist/ui-kit/sections/proof-strip.js.map +1 -1
  27. package/dist/ui-kit/sections/rating-chip.d.ts +15 -5
  28. package/dist/ui-kit/sections/rating-chip.d.ts.map +1 -1
  29. package/dist/ui-kit/sections/rating-chip.js +10 -4
  30. package/dist/ui-kit/sections/rating-chip.js.map +1 -1
  31. package/dist/ui-kit/sections/section-sequence.d.ts +3 -1
  32. package/dist/ui-kit/sections/section-sequence.d.ts.map +1 -1
  33. package/dist/ui-kit/sections/section-sequence.js +4 -2
  34. package/dist/ui-kit/sections/section-sequence.js.map +1 -1
  35. package/dist/ui-kit/sections/signature-section.d.ts +42 -0
  36. package/dist/ui-kit/sections/signature-section.d.ts.map +1 -0
  37. package/dist/ui-kit/sections/signature-section.js +14 -0
  38. package/dist/ui-kit/sections/signature-section.js.map +1 -0
  39. package/dist/ui-kit/shell/call-bar-client.d.ts +2 -1
  40. package/dist/ui-kit/shell/call-bar-client.d.ts.map +1 -1
  41. package/dist/ui-kit/shell/call-bar-client.js +3 -3
  42. package/dist/ui-kit/shell/call-bar-client.js.map +1 -1
  43. package/dist/ui-kit/shell/mobile-call-bar.d.ts +6 -2
  44. package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -1
  45. package/dist/ui-kit/shell/mobile-call-bar.js +5 -2
  46. package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -1
  47. package/dist/ui-kit/structure.css +137 -2
  48. package/package.json +2 -2
@@ -5,6 +5,9 @@
5
5
  * focus (v2) and while focus is inside the footer or a call path. The hook keeps `--bl-callbar-height` at the bar's height while it shows and `0px` otherwise, which
6
6
  * drives `scroll-padding-bottom` (WCAG 2.4.11), and publishes its state (`data-bl-callbar` on the root element and a
7
7
  * `bl:callbar` event) so back-to-top stays hidden while the bar shows: on a phone the button never covers the bar.
8
+ *
9
+ * `always` (3.16.0, a site's recorded choice): the bar shows from the first phone screen, beside the hero's own call
10
+ * path, and still hides over the footer, a dialog, a focused field and focus inside a call path.
8
11
  */
9
12
  import { type RefObject } from 'react';
10
13
  /**
@@ -12,5 +15,7 @@ import { type RefObject } from 'react';
12
15
  * is seeded from their boxes before paint, so the bar never flashes on load or on a client navigation while the
13
16
  * observer's first report is pending.
14
17
  */
15
- export declare function useStickyCallBar(rootRef: RefObject<HTMLElement | null>, resetKey: unknown): boolean;
18
+ export declare function useStickyCallBar(rootRef: RefObject<HTMLElement | null>, resetKey: unknown, options?: {
19
+ readonly always?: boolean;
20
+ }): boolean;
16
21
  //# sourceMappingURL=use-sticky-call-bar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-sticky-call-bar.d.ts","sourceRoot":"","sources":["../../src/navigation/use-sticky-call-bar.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAyCjE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAmEnG"}
1
+ {"version":3,"file":"use-sticky-call-bar.d.ts","sourceRoot":"","sources":["../../src/navigation/use-sticky-call-bar.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAyCjE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAqEhJ"}
@@ -6,6 +6,9 @@
6
6
  * focus (v2) and while focus is inside the footer or a call path. The hook keeps `--bl-callbar-height` at the bar's height while it shows and `0px` otherwise, which
7
7
  * drives `scroll-padding-bottom` (WCAG 2.4.11), and publishes its state (`data-bl-callbar` on the root element and a
8
8
  * `bl:callbar` event) so back-to-top stays hidden while the bar shows: on a phone the button never covers the bar.
9
+ *
10
+ * `always` (3.16.0, a site's recorded choice): the bar shows from the first phone screen, beside the hero's own call
11
+ * path, and still hides over the footer, a dialog, a focused field and focus inside a call path.
9
12
  */
10
13
  import { useLayoutEffect, useState } from 'react';
11
14
  import { CALL_BAR_MEDIA_QUERY, CALL_BAR_STATE_ATTRIBUTE, CALL_BAR_STATE_EVENT, CALL_PATH_SELECTOR } from './constants.js';
@@ -48,8 +51,9 @@ function inViewport(element) {
48
51
  * is seeded from their boxes before paint, so the bar never flashes on load or on a client navigation while the
49
52
  * observer's first report is pending.
50
53
  */
51
- export function useStickyCallBar(rootRef, resetKey) {
52
- const [shown, setShown] = useState(false);
54
+ export function useStickyCallBar(rootRef, resetKey, options = {}) {
55
+ const always = options.always === true;
56
+ const [shown, setShown] = useState(always);
53
57
  useLayoutEffect(() => {
54
58
  const root = rootRef.current;
55
59
  if (!root)
@@ -82,7 +86,8 @@ export function useStickyCallBar(rootRef, resetKey) {
82
86
  update();
83
87
  });
84
88
  }
85
- for (const target of [...document.querySelectorAll(CALL_PATH_SELECTOR), ...pageFooters()]) {
89
+ const callPaths = always ? [] : [...document.querySelectorAll(CALL_PATH_SELECTOR)];
90
+ for (const target of [...callPaths, ...pageFooters()]) {
86
91
  if (inViewport(target))
87
92
  onScreen.add(target);
88
93
  intersections?.observe(target);
@@ -113,7 +118,7 @@ export function useStickyCallBar(rootRef, resetKey) {
113
118
  html.removeAttribute(CALL_BAR_STATE_ATTRIBUTE);
114
119
  document.dispatchEvent(new CustomEvent(CALL_BAR_STATE_EVENT, { detail: { shown: false } }));
115
120
  };
116
- }, [rootRef, resetKey]);
121
+ }, [rootRef, resetKey, always]);
117
122
  return shown;
118
123
  }
119
124
  //# sourceMappingURL=use-sticky-call-bar.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-sticky-call-bar.js","sourceRoot":"","sources":["../../src/navigation/use-sticky-call-bar.ts"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\n/**\n * F6: when the phone call bar shows. TotalCare's logic, ported: below 1024 px the bar shows once every call path on\n * screen (the hero's own call and quote buttons, marked `data-bl-call-path`) has scrolled out, and hides again while\n * a call path, the page footer or an open dialog (the drawer, the quote dialog) is on screen, while a form field has\n * focus (v2) and while focus is inside the footer or a call path. The hook keeps `--bl-callbar-height` at the bar's height while it shows and `0px` otherwise, which\n * drives `scroll-padding-bottom` (WCAG 2.4.11), and publishes its state (`data-bl-callbar` on the root element and a\n * `bl:callbar` event) so back-to-top stays hidden while the bar shows: on a phone the button never covers the bar.\n */\nimport { useLayoutEffect, useState, type RefObject } from 'react'\nimport { CALL_BAR_MEDIA_QUERY, CALL_BAR_STATE_ATTRIBUTE, CALL_BAR_STATE_EVENT, CALL_PATH_SELECTOR } from './constants.js'\n\nconst FIELD_SELECTOR = [\n 'input:not([type=\"button\"], [type=\"submit\"], [type=\"reset\"], [type=\"checkbox\"], [type=\"radio\"], [type=\"hidden\"])',\n 'textarea',\n 'select',\n '[contenteditable=\"\"]',\n '[contenteditable=\"true\"]',\n].join(', ')\n\nfunction isField(target: EventTarget | null): boolean {\n return target instanceof Element && target.matches(FIELD_SELECTOR)\n}\n\n/** The page footer: the shared footer, or a `<footer>` that isn't inside an article, aside, main, nav or section. */\nfunction isPageFooter(element: Element): boolean {\n return element.matches('[data-bl=\"footer\"]') || !element.parentElement?.closest('article, aside, main, nav, section')\n}\n\nfunction pageFooters(): Element[] {\n return Array.from(document.querySelectorAll('footer, [data-bl=\"footer\"]')).filter(isPageFooter)\n}\n\n/**\n * Focus inside the footer or a call path hides the bar at once, before the observer reports (fast Tab stops would\n * otherwise sit under the bar, K5).\n */\nfunction inHideZone(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n if (target.closest(CALL_PATH_SELECTOR)) return true\n const footer = target.closest('footer, [data-bl=\"footer\"]')\n return footer !== null && isPageFooter(footer)\n}\n\n/** True when any part of the element's box is inside the viewport. */\nfunction inViewport(element: Element): boolean {\n const box = element.getBoundingClientRect()\n return box.bottom > 0 && box.right > 0 && box.top < window.innerHeight && box.left < window.innerWidth\n}\n\n/**\n * True while the bar should show. `resetKey` (the route) re-collects the call paths and the footer. The first state\n * is seeded from their boxes before paint, so the bar never flashes on load or on a client navigation while the\n * observer's first report is pending.\n */\nexport function useStickyCallBar(rootRef: RefObject<HTMLElement | null>, resetKey: unknown): boolean {\n const [shown, setShown] = useState(false)\n\n useLayoutEffect(() => {\n const root = rootRef.current\n if (!root) return\n const html = document.documentElement\n const narrow = typeof window.matchMedia === 'function' ? window.matchMedia(CALL_BAR_MEDIA_QUERY) : null\n const onScreen = new Set<Element>()\n let fieldFocused = isField(document.activeElement)\n let focusHidden = inHideZone(document.activeElement)\n\n let published: boolean | undefined\n const update = () => {\n const next = (narrow?.matches ?? false) && onScreen.size === 0 && !fieldFocused && !focusHidden && !document.querySelector('dialog[open]')\n setShown(next)\n html.style.setProperty('--bl-callbar-height', next ? `${Math.round(root.getBoundingClientRect().height)}px` : '0px')\n if (next === published) return\n published = next\n html.setAttribute(CALL_BAR_STATE_ATTRIBUTE, next ? 'shown' : 'hidden')\n document.dispatchEvent(new CustomEvent(CALL_BAR_STATE_EVENT, { detail: { shown: next } }))\n }\n\n let intersections: IntersectionObserver | undefined\n if (typeof IntersectionObserver === 'function') {\n intersections = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) onScreen.add(entry.target)\n else onScreen.delete(entry.target)\n }\n update()\n })\n }\n for (const target of [...document.querySelectorAll(CALL_PATH_SELECTOR), ...pageFooters()]) {\n if (inViewport(target)) onScreen.add(target)\n intersections?.observe(target)\n }\n const dialogs = new MutationObserver(update)\n dialogs.observe(document.body, { subtree: true, attributes: true, attributeFilter: ['open'] })\n const onFocusIn = (event: FocusEvent) => {\n fieldFocused = isField(event.target)\n focusHidden = inHideZone(event.target)\n update()\n }\n const onFocusOut = (event: FocusEvent) => {\n fieldFocused = isField(event.relatedTarget)\n focusHidden = inHideZone(event.relatedTarget)\n update()\n }\n document.addEventListener('focusin', onFocusIn)\n document.addEventListener('focusout', onFocusOut)\n narrow?.addEventListener('change', update)\n update()\n\n return () => {\n intersections?.disconnect()\n dialogs.disconnect()\n document.removeEventListener('focusin', onFocusIn)\n document.removeEventListener('focusout', onFocusOut)\n narrow?.removeEventListener('change', update)\n html.style.removeProperty('--bl-callbar-height')\n html.removeAttribute(CALL_BAR_STATE_ATTRIBUTE)\n document.dispatchEvent(new CustomEvent(CALL_BAR_STATE_EVENT, { detail: { shown: false } }))\n }\n }, [rootRef, resetKey])\n\n return shown\n}\n"]}
1
+ {"version":3,"file":"use-sticky-call-bar.js","sourceRoot":"","sources":["../../src/navigation/use-sticky-call-bar.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAEzH,MAAM,cAAc,GAAG;IACrB,iHAAiH;IACjH,UAAU;IACV,QAAQ;IACR,sBAAsB;IACtB,0BAA0B;CAC3B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAEZ,SAAS,OAAO,CAAC,MAA0B;IACzC,OAAO,MAAM,YAAY,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;AACpE,CAAC;AAED,qHAAqH;AACrH,SAAS,YAAY,CAAC,OAAgB;IACpC,OAAO,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,oCAAoC,CAAC,CAAA;AACvH,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,4BAA4B,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAA;AACjG,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,MAA0B;IAC5C,IAAI,CAAC,CAAC,MAAM,YAAY,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IAC9C,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC;QAAE,OAAO,IAAI,CAAA;IACnD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAA;IAC3D,OAAO,MAAM,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,CAAC,CAAA;AAChD,CAAC;AAED,sEAAsE;AACtE,SAAS,UAAU,CAAC,OAAgB;IAClC,MAAM,GAAG,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAA;IAC3C,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC,IAAI,GAAG,MAAM,CAAC,UAAU,CAAA;AACxG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAsC,EAAE,QAAiB,EAAE,UAAyC,EAAE;IACrI,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,IAAI,CAAA;IACtC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA;IAE1C,eAAe,CAAC,GAAG,EAAE;QACnB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAA;QAC5B,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAA;QACrC,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QACvG,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAW,CAAA;QACnC,IAAI,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;QAClD,IAAI,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;QAEpD,IAAI,SAA8B,CAAA;QAClC,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,CAAA;YAC1I,QAAQ,CAAC,IAAI,CAAC,CAAA;YACd,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;YACpH,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAM;YAC9B,SAAS,GAAG,IAAI,CAAA;YAChB,IAAI,CAAC,YAAY,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YACtE,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5F,CAAC,CAAA;QAED,IAAI,aAA+C,CAAA;QACnD,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE,CAAC;YAC/C,aAAa,GAAG,IAAI,oBAAoB,CAAC,CAAC,OAAO,EAAE,EAAE;gBACnD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IAAI,KAAK,CAAC,cAAc;wBAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;;wBAC/C,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;gBACpC,CAAC;gBACD,MAAM,EAAE,CAAA;YACV,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC,CAAA;QAClF,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,SAAS,EAAE,GAAG,WAAW,EAAE,CAAC,EAAE,CAAC;YACtD,IAAI,UAAU,CAAC,MAAM,CAAC;gBAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAC5C,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;QAChC,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAA;QAC5C,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC9F,MAAM,SAAS,GAAG,CAAC,KAAiB,EAAE,EAAE;YACtC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACpC,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACtC,MAAM,EAAE,CAAA;QACV,CAAC,CAAA;QACD,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAE,EAAE;YACvC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;YAC3C,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;YAC7C,MAAM,EAAE,CAAA;QACV,CAAC,CAAA;QACD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAC/C,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;QACjD,MAAM,EAAE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAC1C,MAAM,EAAE,CAAA;QAER,OAAO,GAAG,EAAE;YACV,aAAa,EAAE,UAAU,EAAE,CAAA;YAC3B,OAAO,CAAC,UAAU,EAAE,CAAA;YACpB,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YAClD,QAAQ,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YACpD,MAAM,EAAE,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAA;YAChD,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAA;YAC9C,QAAQ,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAA;QAC7F,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAA;IAE/B,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["'use client'\n\n/**\n * F6: when the phone call bar shows. TotalCare's logic, ported: below 1024 px the bar shows once every call path on\n * screen (the hero's own call and quote buttons, marked `data-bl-call-path`) has scrolled out, and hides again while\n * a call path, the page footer or an open dialog (the drawer, the quote dialog) is on screen, while a form field has\n * focus (v2) and while focus is inside the footer or a call path. The hook keeps `--bl-callbar-height` at the bar's height while it shows and `0px` otherwise, which\n * drives `scroll-padding-bottom` (WCAG 2.4.11), and publishes its state (`data-bl-callbar` on the root element and a\n * `bl:callbar` event) so back-to-top stays hidden while the bar shows: on a phone the button never covers the bar.\n *\n * `always` (3.16.0, a site's recorded choice): the bar shows from the first phone screen, beside the hero's own call\n * path, and still hides over the footer, a dialog, a focused field and focus inside a call path.\n */\nimport { useLayoutEffect, useState, type RefObject } from 'react'\nimport { CALL_BAR_MEDIA_QUERY, CALL_BAR_STATE_ATTRIBUTE, CALL_BAR_STATE_EVENT, CALL_PATH_SELECTOR } from './constants.js'\n\nconst FIELD_SELECTOR = [\n 'input:not([type=\"button\"], [type=\"submit\"], [type=\"reset\"], [type=\"checkbox\"], [type=\"radio\"], [type=\"hidden\"])',\n 'textarea',\n 'select',\n '[contenteditable=\"\"]',\n '[contenteditable=\"true\"]',\n].join(', ')\n\nfunction isField(target: EventTarget | null): boolean {\n return target instanceof Element && target.matches(FIELD_SELECTOR)\n}\n\n/** The page footer: the shared footer, or a `<footer>` that isn't inside an article, aside, main, nav or section. */\nfunction isPageFooter(element: Element): boolean {\n return element.matches('[data-bl=\"footer\"]') || !element.parentElement?.closest('article, aside, main, nav, section')\n}\n\nfunction pageFooters(): Element[] {\n return Array.from(document.querySelectorAll('footer, [data-bl=\"footer\"]')).filter(isPageFooter)\n}\n\n/**\n * Focus inside the footer or a call path hides the bar at once, before the observer reports (fast Tab stops would\n * otherwise sit under the bar, K5).\n */\nfunction inHideZone(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false\n if (target.closest(CALL_PATH_SELECTOR)) return true\n const footer = target.closest('footer, [data-bl=\"footer\"]')\n return footer !== null && isPageFooter(footer)\n}\n\n/** True when any part of the element's box is inside the viewport. */\nfunction inViewport(element: Element): boolean {\n const box = element.getBoundingClientRect()\n return box.bottom > 0 && box.right > 0 && box.top < window.innerHeight && box.left < window.innerWidth\n}\n\n/**\n * True while the bar should show. `resetKey` (the route) re-collects the call paths and the footer. The first state\n * is seeded from their boxes before paint, so the bar never flashes on load or on a client navigation while the\n * observer's first report is pending.\n */\nexport function useStickyCallBar(rootRef: RefObject<HTMLElement | null>, resetKey: unknown, options: { readonly always?: boolean } = {}): boolean {\n const always = options.always === true\n const [shown, setShown] = useState(always)\n\n useLayoutEffect(() => {\n const root = rootRef.current\n if (!root) return\n const html = document.documentElement\n const narrow = typeof window.matchMedia === 'function' ? window.matchMedia(CALL_BAR_MEDIA_QUERY) : null\n const onScreen = new Set<Element>()\n let fieldFocused = isField(document.activeElement)\n let focusHidden = inHideZone(document.activeElement)\n\n let published: boolean | undefined\n const update = () => {\n const next = (narrow?.matches ?? false) && onScreen.size === 0 && !fieldFocused && !focusHidden && !document.querySelector('dialog[open]')\n setShown(next)\n html.style.setProperty('--bl-callbar-height', next ? `${Math.round(root.getBoundingClientRect().height)}px` : '0px')\n if (next === published) return\n published = next\n html.setAttribute(CALL_BAR_STATE_ATTRIBUTE, next ? 'shown' : 'hidden')\n document.dispatchEvent(new CustomEvent(CALL_BAR_STATE_EVENT, { detail: { shown: next } }))\n }\n\n let intersections: IntersectionObserver | undefined\n if (typeof IntersectionObserver === 'function') {\n intersections = new IntersectionObserver((entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting) onScreen.add(entry.target)\n else onScreen.delete(entry.target)\n }\n update()\n })\n }\n const callPaths = always ? [] : [...document.querySelectorAll(CALL_PATH_SELECTOR)]\n for (const target of [...callPaths, ...pageFooters()]) {\n if (inViewport(target)) onScreen.add(target)\n intersections?.observe(target)\n }\n const dialogs = new MutationObserver(update)\n dialogs.observe(document.body, { subtree: true, attributes: true, attributeFilter: ['open'] })\n const onFocusIn = (event: FocusEvent) => {\n fieldFocused = isField(event.target)\n focusHidden = inHideZone(event.target)\n update()\n }\n const onFocusOut = (event: FocusEvent) => {\n fieldFocused = isField(event.relatedTarget)\n focusHidden = inHideZone(event.relatedTarget)\n update()\n }\n document.addEventListener('focusin', onFocusIn)\n document.addEventListener('focusout', onFocusOut)\n narrow?.addEventListener('change', update)\n update()\n\n return () => {\n intersections?.disconnect()\n dialogs.disconnect()\n document.removeEventListener('focusin', onFocusIn)\n document.removeEventListener('focusout', onFocusOut)\n narrow?.removeEventListener('change', update)\n html.style.removeProperty('--bl-callbar-height')\n html.removeAttribute(CALL_BAR_STATE_ATTRIBUTE)\n document.dispatchEvent(new CustomEvent(CALL_BAR_STATE_EVENT, { detail: { shown: false } }))\n }\n }, [rootRef, resetKey, always])\n\n return shown\n}\n"]}
@@ -51,6 +51,7 @@ import type { BeforeAfterSkin } from './sections/before-after.js';
51
51
  import type { LicencesSkin } from './sections/licences.js';
52
52
  import type { QuoteChecklistSkin } from './sections/quote-checklist.js';
53
53
  import type { EmergencyBandSkin } from './sections/emergency-band.js';
54
+ import type { SignatureSectionSkin } from './sections/signature-section.js';
54
55
  export interface BrandlabSkin {
55
56
  readonly buttonLink?: ButtonLinkSkin;
56
57
  readonly textLink?: TextLinkSkin;
@@ -106,5 +107,6 @@ export interface BrandlabSkin {
106
107
  readonly licences?: LicencesSkin;
107
108
  readonly quoteChecklist?: QuoteChecklistSkin;
108
109
  readonly emergencyBand?: EmergencyBandSkin;
110
+ readonly signatureSection?: SignatureSectionSkin;
109
111
  }
110
112
  //# sourceMappingURL=brandlab-skin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brandlab-skin.d.ts","sourceRoot":"","sources":["../../src/ui-kit/brandlab-skin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"brandlab-skin.d.ts","sourceRoot":"","sources":["../../src/ui-kit/brandlab-skin.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"brandlab-skin.js","sourceRoot":"","sources":["../../src/ui-kit/brandlab-skin.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * A site's whole look for the ui-kit: one entry per shared component it renders (`src/site/skin.ts`, written with\n * `satisfies BrandlabSkin`). Each release adds the entries for its components. K2 checks that every rendered\n * component has an entry and that no reference-skin class ships.\n */\nimport type { ButtonLinkSkin, PhoneLinkSkin, TextLinkSkin } from './primitives/links.js'\nimport type { QuoteButtonSkin } from './primitives/quote-button.js'\nimport type { ContainerSkin, EyebrowSkin, SectionHeadingSkin } from './primitives/layout.js'\nimport type { BadgeSkin, ChipSkin } from './primitives/badge.js'\nimport type { ButtonSkin } from './primitives/button.js'\nimport type { CardSkin } from './primitives/card.js'\nimport type { LinkListSkin, TickListSkin } from './primitives/lists.js'\nimport type { MediaFrameSkin } from './primitives/media-frame.js'\nimport type { StatSkin } from './primitives/stat.js'\nimport type { BackToTopSkin } from './shell/back-to-top.js'\nimport type { MobileCallBarSkin } from './shell/mobile-call-bar.js'\nimport type { MobileDrawerSkin } from './shell/mobile-drawer.js'\nimport type { SiteHeaderSkin } from './shell/site-header.js'\nimport type { UtilityBarSkin } from './shell/utility-bar.js'\nimport type { DialogSkin } from './form/dialog.js'\nimport type { FieldSkin } from './form/field.js'\nimport type { PhotoUploadSkin } from './form/photo-upload.js'\nimport type { QuoteDialogSkin } from './form/quote-dialog.js'\nimport type { QuoteFormSkin } from './form/quote-form.js'\nimport type { ThankYouSkin } from './form/thank-you.js'\nimport type { CTABandSkin } from './sections/cta-band.js'\nimport type { RatingChipSkin } from './sections/rating-chip.js'\nimport type { ReviewsBandSkin } from './sections/reviews-band.js'\nimport type { SiteFooterSkin } from './sections/site-footer.js'\nimport type { AccordionSkin } from './sections/accordion.js'\nimport type { ContactBlockSkin } from './sections/contact-block.js'\nimport type { FAQsSkin } from './sections/faqs.js'\nimport type { PageHeaderSkin } from './sections/page-header.js'\nimport type { PriceGuideSkin } from './sections/price-guide.js'\nimport type { PriceTableSkin } from './sections/price-table.js'\nimport type { ProofStripSkin } from './sections/proof-strip.js'\nimport type { HeroSkin } from './sections/hero.js'\nimport type { ServicesGridSkin } from './sections/services-grid.js'\nimport type { MediaSkin } from './primitives/media.js'\nimport type { BreadcrumbsSkin } from './primitives/breadcrumbs.js'\nimport type { CouncilRulesSkin } from './sections/council-rules.js'\nimport type { CoverageSkin } from './sections/coverage.js'\nimport type { LocalFactsSkin } from './sections/local-facts.js'\nimport type { AreaMapSkin } from './sections/area-map.js'\nimport type { NearbyAreasSkin } from './sections/nearby-areas.js'\nimport type { NearbyJobsSkin } from './sections/nearby-jobs.js'\nimport type { RelatedServicesSkin } from './sections/related-services.js'\nimport type { ProjectsSkin } from './sections/projects.js'\nimport type { GallerySkin } from './sections/gallery.js'\nimport type { BeforeAfterSkin } from './sections/before-after.js'\nimport type { LicencesSkin } from './sections/licences.js'\nimport type { QuoteChecklistSkin } from './sections/quote-checklist.js'\nimport type { EmergencyBandSkin } from './sections/emergency-band.js'\n\nexport interface BrandlabSkin {\n readonly buttonLink?: ButtonLinkSkin\n readonly textLink?: TextLinkSkin\n readonly phoneLink?: PhoneLinkSkin\n readonly quoteButton?: QuoteButtonSkin\n readonly container?: ContainerSkin\n readonly sectionHeading?: SectionHeadingSkin\n // primitives (3.14.0)\n readonly button?: ButtonSkin\n readonly eyebrow?: EyebrowSkin\n readonly card?: CardSkin\n readonly badge?: BadgeSkin\n readonly chip?: ChipSkin\n readonly stat?: StatSkin\n readonly tickList?: TickListSkin\n readonly linkList?: LinkListSkin\n readonly mediaFrame?: MediaFrameSkin\n readonly siteHeader?: SiteHeaderSkin\n readonly mobileDrawer?: MobileDrawerSkin\n readonly utilityBar?: UtilityBarSkin\n readonly mobileCallBar?: MobileCallBarSkin\n readonly backToTop?: BackToTopSkin\n // form (3.10.0)\n readonly quoteForm?: QuoteFormSkin\n readonly quoteDialog?: QuoteDialogSkin\n readonly photoUpload?: PhotoUploadSkin\n readonly dialog?: DialogSkin\n readonly field?: FieldSkin\n readonly thankYou?: ThankYouSkin\n readonly ratingChip?: RatingChipSkin\n readonly reviewsBand?: ReviewsBandSkin\n readonly ctaBand?: CTABandSkin\n readonly siteFooter?: SiteFooterSkin\n readonly accordion?: AccordionSkin\n readonly faqs?: FAQsSkin\n readonly priceTable?: PriceTableSkin\n readonly priceGuide?: PriceGuideSkin\n readonly proofStrip?: ProofStripSkin\n readonly pageHeader?: PageHeaderSkin\n readonly contactBlock?: ContactBlockSkin\n // hero (3.14.0)\n readonly hero?: HeroSkin\n // 3.14.0\n readonly servicesGrid?: ServicesGridSkin\n readonly media?: MediaSkin\n readonly breadcrumbs?: BreadcrumbsSkin\n // location sections (3.15.0)\n readonly localFacts?: LocalFactsSkin\n readonly councilRules?: CouncilRulesSkin\n readonly nearbyJobs?: NearbyJobsSkin\n readonly nearbyAreas?: NearbyAreasSkin\n readonly areaMap?: AreaMapSkin\n readonly coverage?: CoverageSkin\n readonly relatedServices?: RelatedServicesSkin\n // proof sections (3.15.0)\n readonly projects?: ProjectsSkin\n readonly gallery?: GallerySkin\n readonly beforeAfter?: BeforeAfterSkin\n readonly licences?: LicencesSkin\n readonly quoteChecklist?: QuoteChecklistSkin\n readonly emergencyBand?: EmergencyBandSkin\n}\n"]}
1
+ {"version":3,"file":"brandlab-skin.js","sourceRoot":"","sources":["../../src/ui-kit/brandlab-skin.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * A site's whole look for the ui-kit: one entry per shared component it renders (`src/site/skin.ts`, written with\n * `satisfies BrandlabSkin`). Each release adds the entries for its components. K2 checks that every rendered\n * component has an entry and that no reference-skin class ships.\n */\nimport type { ButtonLinkSkin, PhoneLinkSkin, TextLinkSkin } from './primitives/links.js'\nimport type { QuoteButtonSkin } from './primitives/quote-button.js'\nimport type { ContainerSkin, EyebrowSkin, SectionHeadingSkin } from './primitives/layout.js'\nimport type { BadgeSkin, ChipSkin } from './primitives/badge.js'\nimport type { ButtonSkin } from './primitives/button.js'\nimport type { CardSkin } from './primitives/card.js'\nimport type { LinkListSkin, TickListSkin } from './primitives/lists.js'\nimport type { MediaFrameSkin } from './primitives/media-frame.js'\nimport type { StatSkin } from './primitives/stat.js'\nimport type { BackToTopSkin } from './shell/back-to-top.js'\nimport type { MobileCallBarSkin } from './shell/mobile-call-bar.js'\nimport type { MobileDrawerSkin } from './shell/mobile-drawer.js'\nimport type { SiteHeaderSkin } from './shell/site-header.js'\nimport type { UtilityBarSkin } from './shell/utility-bar.js'\nimport type { DialogSkin } from './form/dialog.js'\nimport type { FieldSkin } from './form/field.js'\nimport type { PhotoUploadSkin } from './form/photo-upload.js'\nimport type { QuoteDialogSkin } from './form/quote-dialog.js'\nimport type { QuoteFormSkin } from './form/quote-form.js'\nimport type { ThankYouSkin } from './form/thank-you.js'\nimport type { CTABandSkin } from './sections/cta-band.js'\nimport type { RatingChipSkin } from './sections/rating-chip.js'\nimport type { ReviewsBandSkin } from './sections/reviews-band.js'\nimport type { SiteFooterSkin } from './sections/site-footer.js'\nimport type { AccordionSkin } from './sections/accordion.js'\nimport type { ContactBlockSkin } from './sections/contact-block.js'\nimport type { FAQsSkin } from './sections/faqs.js'\nimport type { PageHeaderSkin } from './sections/page-header.js'\nimport type { PriceGuideSkin } from './sections/price-guide.js'\nimport type { PriceTableSkin } from './sections/price-table.js'\nimport type { ProofStripSkin } from './sections/proof-strip.js'\nimport type { HeroSkin } from './sections/hero.js'\nimport type { ServicesGridSkin } from './sections/services-grid.js'\nimport type { MediaSkin } from './primitives/media.js'\nimport type { BreadcrumbsSkin } from './primitives/breadcrumbs.js'\nimport type { CouncilRulesSkin } from './sections/council-rules.js'\nimport type { CoverageSkin } from './sections/coverage.js'\nimport type { LocalFactsSkin } from './sections/local-facts.js'\nimport type { AreaMapSkin } from './sections/area-map.js'\nimport type { NearbyAreasSkin } from './sections/nearby-areas.js'\nimport type { NearbyJobsSkin } from './sections/nearby-jobs.js'\nimport type { RelatedServicesSkin } from './sections/related-services.js'\nimport type { ProjectsSkin } from './sections/projects.js'\nimport type { GallerySkin } from './sections/gallery.js'\nimport type { BeforeAfterSkin } from './sections/before-after.js'\nimport type { LicencesSkin } from './sections/licences.js'\nimport type { QuoteChecklistSkin } from './sections/quote-checklist.js'\nimport type { EmergencyBandSkin } from './sections/emergency-band.js'\nimport type { SignatureSectionSkin } from './sections/signature-section.js'\n\nexport interface BrandlabSkin {\n readonly buttonLink?: ButtonLinkSkin\n readonly textLink?: TextLinkSkin\n readonly phoneLink?: PhoneLinkSkin\n readonly quoteButton?: QuoteButtonSkin\n readonly container?: ContainerSkin\n readonly sectionHeading?: SectionHeadingSkin\n // primitives (3.14.0)\n readonly button?: ButtonSkin\n readonly eyebrow?: EyebrowSkin\n readonly card?: CardSkin\n readonly badge?: BadgeSkin\n readonly chip?: ChipSkin\n readonly stat?: StatSkin\n readonly tickList?: TickListSkin\n readonly linkList?: LinkListSkin\n readonly mediaFrame?: MediaFrameSkin\n readonly siteHeader?: SiteHeaderSkin\n readonly mobileDrawer?: MobileDrawerSkin\n readonly utilityBar?: UtilityBarSkin\n readonly mobileCallBar?: MobileCallBarSkin\n readonly backToTop?: BackToTopSkin\n // form (3.10.0)\n readonly quoteForm?: QuoteFormSkin\n readonly quoteDialog?: QuoteDialogSkin\n readonly photoUpload?: PhotoUploadSkin\n readonly dialog?: DialogSkin\n readonly field?: FieldSkin\n readonly thankYou?: ThankYouSkin\n readonly ratingChip?: RatingChipSkin\n readonly reviewsBand?: ReviewsBandSkin\n readonly ctaBand?: CTABandSkin\n readonly siteFooter?: SiteFooterSkin\n readonly accordion?: AccordionSkin\n readonly faqs?: FAQsSkin\n readonly priceTable?: PriceTableSkin\n readonly priceGuide?: PriceGuideSkin\n readonly proofStrip?: ProofStripSkin\n readonly pageHeader?: PageHeaderSkin\n readonly contactBlock?: ContactBlockSkin\n // hero (3.14.0)\n readonly hero?: HeroSkin\n // 3.14.0\n readonly servicesGrid?: ServicesGridSkin\n readonly media?: MediaSkin\n readonly breadcrumbs?: BreadcrumbsSkin\n // location sections (3.15.0)\n readonly localFacts?: LocalFactsSkin\n readonly councilRules?: CouncilRulesSkin\n readonly nearbyJobs?: NearbyJobsSkin\n readonly nearbyAreas?: NearbyAreasSkin\n readonly areaMap?: AreaMapSkin\n readonly coverage?: CoverageSkin\n readonly relatedServices?: RelatedServicesSkin\n // proof sections (3.15.0)\n readonly projects?: ProjectsSkin\n readonly gallery?: GallerySkin\n readonly beforeAfter?: BeforeAfterSkin\n readonly licences?: LicencesSkin\n readonly quoteChecklist?: QuoteChecklistSkin\n readonly emergencyBand?: EmergencyBandSkin\n // 3.16.0\n readonly signatureSection?: SignatureSectionSkin\n}\n"]}
@@ -53,7 +53,7 @@ export declare const REPEATED_SLOTS: {
53
53
  };
54
54
  readonly proofStrip: {
55
55
  readonly scope: "[data-bl-section=\"proof-strip\"] [data-slot=\"list\"]";
56
- readonly slots: readonly ["item", "icon", "stars", "value", "label"];
56
+ readonly slots: readonly ["item", "link", "icon", "stars", "value", "label"];
57
57
  };
58
58
  readonly reviewsBand: {
59
59
  readonly scope: "[data-bl-section=\"reviews\"] [data-slot=\"list\"]";
@@ -49,7 +49,7 @@ export const REPEATED_SLOTS = {
49
49
  'figures', 'band', 'factor', 'name', 'effect', 'detail',
50
50
  ],
51
51
  },
52
- proofStrip: { scope: '[data-bl-section="proof-strip"] [data-slot="list"]', slots: ['item', 'icon', 'stars', 'value', 'label'] },
52
+ proofStrip: { scope: '[data-bl-section="proof-strip"] [data-slot="list"]', slots: ['item', 'link', 'icon', 'stars', 'value', 'label'] },
53
53
  reviewsBand: {
54
54
  scope: '[data-bl-section="reviews"] [data-slot="list"]',
55
55
  slots: ['item', 'stars', 'quote', 'more', 'author', 'avatar', 'name', 'date'],
@@ -1 +1 @@
1
- {"version":3,"file":"repeated-slots.js","sourceRoot":"","sources":["../../src/ui-kit/repeated-slots.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The repeated slots of every shared component (3.14.0): the parts a component renders once per entry of a list in\n * its data. They carry their `data-slot` hook and never a class, so a long class string is not repeated in the HTML and\n * the RSC payload for every link, review, star, card or chip. A site styles them once in `src/site/skin.css`:\n *\n * ```css\n * @layer components {\n * [data-bl=\"footer\"] [data-slot=\"link\"] { @apply text-sm text-white/80 hover:text-white; }\n * [data-bl=\"header\"] [data-slot=\"list\"] [data-slot=\"panelLink\"] { padding: 0.5rem 0.75rem; }\n * }\n * ```\n *\n * `scope` is the selector that holds the repeated slots without reaching a nested component that reuses a slot name\n * (the drawer sits inside the header; the rating chip inside the reviews band uses `stars` too).\n * `repeatedSlotSelector()` joins the two. Pure data: safe to import anywhere.\n */\nexport const REPEATED_SLOTS = {\n siteHeader: {\n scope: '[data-bl=\"header\"] [data-slot=\"list\"]',\n slots: [\n 'item', 'itemRow', 'link', 'trigger', 'panel', 'panelBody', 'panelList', 'panelGroup', 'panelHeading', 'panelLink',\n 'panelLabel', 'panelText', 'featured', 'featuredMedia', 'featuredLabel', 'featuredText',\n ],\n },\n mobileDrawer: {\n scope: '[data-bl=\"drawer\"]',\n slots: ['group', 'groupTrigger', 'groupLinks', 'groupLink', 'link', 'socialLink'],\n },\n utilityBar: { scope: '[data-bl=\"utility\"]', slots: ['item', 'licence', 'socialLink'] },\n siteFooter: {\n scope: '[data-bl=\"footer\"]',\n slots: ['licenceLink', 'socialLink', 'column', 'heading', 'toggle', 'list', 'link', 'policyLink'],\n },\n accordion: { scope: '[data-bl=\"accordion\"]', slots: ['item', 'summary', 'label', 'marker', 'content'] },\n faqs: {\n scope: '[data-bl-section=\"faqs\"] [data-slot=\"columns\"]',\n slots: ['column', 'group', 'subheading', 'accordion', 'item', 'summary', 'label', 'marker', 'content'],\n /** The nested accordion's root is its own component: `data-bl=\"accordion\"`, not a `data-slot`. */\n hooks: { accordion: '[data-bl=\"accordion\"]' },\n },\n priceTable: {\n scope: '[data-bl=\"price-table\"]',\n slots: ['row', 'job', 'cell', 'label', 'range', 'unit', 'gst', 'parts', 'part', 'includes', 'excludes'],\n },\n priceGuide: {\n scope: '[data-bl-section=\"price-guide\"]',\n slots: [\n 'row', 'job', 'cell', 'label', 'range', 'unit', 'gst', 'parts', 'part', 'includes', 'excludes', 'card', 'title',\n 'figures', 'band', 'factor', 'name', 'effect', 'detail',\n ],\n },\n proofStrip: { scope: '[data-bl-section=\"proof-strip\"] [data-slot=\"list\"]', slots: ['item', 'icon', 'stars', 'value', 'label'] },\n reviewsBand: {\n scope: '[data-bl-section=\"reviews\"] [data-slot=\"list\"]',\n slots: ['item', 'stars', 'quote', 'more', 'author', 'avatar', 'name', 'date'],\n },\n contactBlock: { scope: '[data-bl-section=\"contact\"] [data-slot=\"details\"]', slots: ['line'] },\n servicesGrid: {\n scope: '[data-bl-section=\"services\"] [data-slot=\"list\"]',\n slots: ['item', 'body', 'media', 'title', 'summary', 'points', 'point', 'action', 'link'],\n },\n breadcrumbs: { scope: '[data-bl=\"breadcrumbs\"]', slots: ['item', 'link', 'current'] },\n // Location sections (3.15.0). Their link lists are `LinkList`s, reached through `linkList` (`[data-bl=\"link-list\"]`).\n localFacts: { scope: '[data-bl-section=\"local-facts\"]', slots: ['fact', 'factSource', 'fee'] },\n councilRules: { scope: '[data-bl-section=\"council-rules\"]', slots: ['fee'] },\n nearbyJobs: { scope: '[data-bl-section=\"nearby-jobs\"] [data-slot=\"list\"]', slots: ['item', 'body', 'media', 'title', 'link', 'outcome'] },\n coverage: { scope: '[data-bl-section=\"coverage\"] [data-slot=\"groups\"]', slots: ['group', 'groupHeading'] },\n relatedServices: {\n scope: '[data-bl-section=\"related-services\"] [data-slot=\"list\"]',\n slots: ['item', 'body', 'media', 'title', 'summary', 'link'],\n },\n // Proof sections (3.15.0). Their photos are nested `[data-bl=\"media\"]` frames; project cards are `[data-bl=\"card\"]`.\n gallery: { scope: '[data-bl-section=\"gallery\"] [data-slot=\"list\"]', slots: ['item', 'link'] },\n beforeAfter: { scope: '[data-bl-section=\"before-after\"] [data-slot=\"list\"]', slots: ['pair', 'frames', 'frame', 'note'] },\n licences: {\n scope: '[data-bl-section=\"licences\"] [data-slot=\"list\"]',\n slots: ['row', 'label', 'value', 'number', 'holder', 'classes', 'class', 'register', 'cover', 'amount'],\n },\n thankYou: { scope: '[data-bl=\"thank-you\"]', slots: ['step'] },\n photoUpload: { scope: '[data-bl=\"photo-upload\"]', slots: ['photo', 'thumb', 'remove'] },\n quoteForm: { scope: '[data-bl=\"quote-form\"] [data-bl=\"photo-upload\"]', slots: ['photo', 'thumb', 'remove'] },\n // Primitives rendered once per list entry (3.14.0): every part is repeated, the root included (style the root\n // through its own hook, `[data-bl=\"card\"]`).\n card: { scope: '[data-bl=\"card\"]', slots: ['media', 'body', 'title', 'link', 'text', 'meta'] },\n badge: { scope: '[data-bl=\"badge\"]', slots: ['icon', 'label'] },\n chip: { scope: '[data-bl=\"chip\"]', slots: ['icon', 'label'] },\n stat: { scope: '[data-bl=\"stat\"]', slots: ['value', 'label', 'link'] },\n tickList: { scope: '[data-bl=\"tick-list\"]', slots: ['item', 'tick', 'text', 'link'] },\n /** A lean list (cost item 1f): plain `<li><a>` entries with no `data-slot`, reached by element. */\n linkList: { scope: '[data-bl=\"link-list\"]', slots: ['item', 'link'], hooks: { item: '> li', link: '> li > a' } },\n} as const\n\nexport type RepeatedSlotComponent = keyof typeof REPEATED_SLOTS\n/** The repeated slots of one component, for example `RepeatedSlotOf<'siteFooter'>` is `'licenceLink' | … | 'policyLink'`. */\nexport type RepeatedSlotOf<Component extends RepeatedSlotComponent> = (typeof REPEATED_SLOTS)[Component]['slots'][number]\n\n/** The selector a skin stylesheet uses for one repeated slot, for example `[data-bl=\"footer\"] [data-slot=\"link\"]`. */\nexport function repeatedSlotSelector<Component extends RepeatedSlotComponent>(component: Component, slot: RepeatedSlotOf<Component>): string {\n const entry: { readonly scope: string; readonly hooks?: Readonly<Record<string, string>> } = REPEATED_SLOTS[component]\n return `${entry.scope} ${entry.hooks?.[slot] ?? `[data-slot=\"${slot}\"]`}`\n}\n"]}
1
+ {"version":3,"file":"repeated-slots.js","sourceRoot":"","sources":["../../src/ui-kit/repeated-slots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU,EAAE;QACV,KAAK,EAAE,uCAAuC;QAC9C,KAAK,EAAE;YACL,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW;YAClH,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc;SACxF;KACF;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,oBAAoB;QAC3B,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC;KAClF;IACD,UAAU,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE;IACtF,UAAU,EAAE;QACV,KAAK,EAAE,oBAAoB;QAC3B,KAAK,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC;KAClG;IACD,SAAS,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;IACvG,IAAI,EAAE;QACJ,KAAK,EAAE,gDAAgD;QACvD,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;QACtG,kGAAkG;QAClG,KAAK,EAAE,EAAE,SAAS,EAAE,uBAAuB,EAAE;KAC9C;IACD,UAAU,EAAE;QACV,KAAK,EAAE,yBAAyB;QAChC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC;KACxG;IACD,UAAU,EAAE;QACV,KAAK,EAAE,iCAAiC;QACxC,KAAK,EAAE;YACL,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO;YAC/G,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ;SACxD;KACF;IACD,UAAU,EAAE,EAAE,KAAK,EAAE,oDAAoD,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;IACvI,WAAW,EAAE;QACX,KAAK,EAAE,gDAAgD;QACvD,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;KAC9E;IACD,YAAY,EAAE,EAAE,KAAK,EAAE,mDAAmD,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;IAC7F,YAAY,EAAE;QACZ,KAAK,EAAE,iDAAiD;QACxD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;KAC1F;IACD,WAAW,EAAE,EAAE,KAAK,EAAE,yBAAyB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE;IACrF,sHAAsH;IACtH,UAAU,EAAE,EAAE,KAAK,EAAE,iCAAiC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE;IAC9F,YAAY,EAAE,EAAE,KAAK,EAAE,mCAAmC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE;IAC5E,UAAU,EAAE,EAAE,KAAK,EAAE,oDAAoD,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE;IACzI,QAAQ,EAAE,EAAE,KAAK,EAAE,mDAAmD,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE;IAC1G,eAAe,EAAE;QACf,KAAK,EAAE,yDAAyD;QAChE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;KAC7D;IACD,qHAAqH;IACrH,OAAO,EAAE,EAAE,KAAK,EAAE,gDAAgD,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;IAC7F,WAAW,EAAE,EAAE,KAAK,EAAE,qDAAqD,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE;IACzH,QAAQ,EAAE;QACR,KAAK,EAAE,iDAAiD;QACxD,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,CAAC;KACxG;IACD,QAAQ,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;IAC7D,WAAW,EAAE,EAAE,KAAK,EAAE,0BAA0B,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE;IACvF,SAAS,EAAE,EAAE,KAAK,EAAE,iDAAiD,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE;IAC5G,8GAA8G;IAC9G,6CAA6C;IAC7C,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;IAC9F,KAAK,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;IAC/D,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;IAC7D,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE;IACtE,QAAQ,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE;IACrF,mGAAmG;IACnG,QAAQ,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE;CACxG,CAAA;AAMV,sHAAsH;AACtH,MAAM,UAAU,oBAAoB,CAA0C,SAAoB,EAAE,IAA+B;IACjI,MAAM,KAAK,GAAkF,cAAc,CAAC,SAAS,CAAC,CAAA;IACtH,OAAO,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,eAAe,IAAI,IAAI,EAAE,CAAA;AAC3E,CAAC","sourcesContent":["/**\n * The repeated slots of every shared component (3.14.0): the parts a component renders once per entry of a list in\n * its data. They carry their `data-slot` hook and never a class, so a long class string is not repeated in the HTML and\n * the RSC payload for every link, review, star, card or chip. A site styles them once in `src/site/skin.css`:\n *\n * ```css\n * @layer components {\n * [data-bl=\"footer\"] [data-slot=\"link\"] { @apply text-sm text-white/80 hover:text-white; }\n * [data-bl=\"header\"] [data-slot=\"list\"] [data-slot=\"panelLink\"] { padding: 0.5rem 0.75rem; }\n * }\n * ```\n *\n * `scope` is the selector that holds the repeated slots without reaching a nested component that reuses a slot name\n * (the drawer sits inside the header; the rating chip inside the reviews band uses `stars` too).\n * `repeatedSlotSelector()` joins the two. Pure data: safe to import anywhere.\n */\nexport const REPEATED_SLOTS = {\n siteHeader: {\n scope: '[data-bl=\"header\"] [data-slot=\"list\"]',\n slots: [\n 'item', 'itemRow', 'link', 'trigger', 'panel', 'panelBody', 'panelList', 'panelGroup', 'panelHeading', 'panelLink',\n 'panelLabel', 'panelText', 'featured', 'featuredMedia', 'featuredLabel', 'featuredText',\n ],\n },\n mobileDrawer: {\n scope: '[data-bl=\"drawer\"]',\n slots: ['group', 'groupTrigger', 'groupLinks', 'groupLink', 'link', 'socialLink'],\n },\n utilityBar: { scope: '[data-bl=\"utility\"]', slots: ['item', 'licence', 'socialLink'] },\n siteFooter: {\n scope: '[data-bl=\"footer\"]',\n slots: ['licenceLink', 'socialLink', 'column', 'heading', 'toggle', 'list', 'link', 'policyLink'],\n },\n accordion: { scope: '[data-bl=\"accordion\"]', slots: ['item', 'summary', 'label', 'marker', 'content'] },\n faqs: {\n scope: '[data-bl-section=\"faqs\"] [data-slot=\"columns\"]',\n slots: ['column', 'group', 'subheading', 'accordion', 'item', 'summary', 'label', 'marker', 'content'],\n /** The nested accordion's root is its own component: `data-bl=\"accordion\"`, not a `data-slot`. */\n hooks: { accordion: '[data-bl=\"accordion\"]' },\n },\n priceTable: {\n scope: '[data-bl=\"price-table\"]',\n slots: ['row', 'job', 'cell', 'label', 'range', 'unit', 'gst', 'parts', 'part', 'includes', 'excludes'],\n },\n priceGuide: {\n scope: '[data-bl-section=\"price-guide\"]',\n slots: [\n 'row', 'job', 'cell', 'label', 'range', 'unit', 'gst', 'parts', 'part', 'includes', 'excludes', 'card', 'title',\n 'figures', 'band', 'factor', 'name', 'effect', 'detail',\n ],\n },\n proofStrip: { scope: '[data-bl-section=\"proof-strip\"] [data-slot=\"list\"]', slots: ['item', 'link', 'icon', 'stars', 'value', 'label'] },\n reviewsBand: {\n scope: '[data-bl-section=\"reviews\"] [data-slot=\"list\"]',\n slots: ['item', 'stars', 'quote', 'more', 'author', 'avatar', 'name', 'date'],\n },\n contactBlock: { scope: '[data-bl-section=\"contact\"] [data-slot=\"details\"]', slots: ['line'] },\n servicesGrid: {\n scope: '[data-bl-section=\"services\"] [data-slot=\"list\"]',\n slots: ['item', 'body', 'media', 'title', 'summary', 'points', 'point', 'action', 'link'],\n },\n breadcrumbs: { scope: '[data-bl=\"breadcrumbs\"]', slots: ['item', 'link', 'current'] },\n // Location sections (3.15.0). Their link lists are `LinkList`s, reached through `linkList` (`[data-bl=\"link-list\"]`).\n localFacts: { scope: '[data-bl-section=\"local-facts\"]', slots: ['fact', 'factSource', 'fee'] },\n councilRules: { scope: '[data-bl-section=\"council-rules\"]', slots: ['fee'] },\n nearbyJobs: { scope: '[data-bl-section=\"nearby-jobs\"] [data-slot=\"list\"]', slots: ['item', 'body', 'media', 'title', 'link', 'outcome'] },\n coverage: { scope: '[data-bl-section=\"coverage\"] [data-slot=\"groups\"]', slots: ['group', 'groupHeading'] },\n relatedServices: {\n scope: '[data-bl-section=\"related-services\"] [data-slot=\"list\"]',\n slots: ['item', 'body', 'media', 'title', 'summary', 'link'],\n },\n // Proof sections (3.15.0). Their photos are nested `[data-bl=\"media\"]` frames; project cards are `[data-bl=\"card\"]`.\n gallery: { scope: '[data-bl-section=\"gallery\"] [data-slot=\"list\"]', slots: ['item', 'link'] },\n beforeAfter: { scope: '[data-bl-section=\"before-after\"] [data-slot=\"list\"]', slots: ['pair', 'frames', 'frame', 'note'] },\n licences: {\n scope: '[data-bl-section=\"licences\"] [data-slot=\"list\"]',\n slots: ['row', 'label', 'value', 'number', 'holder', 'classes', 'class', 'register', 'cover', 'amount'],\n },\n thankYou: { scope: '[data-bl=\"thank-you\"]', slots: ['step'] },\n photoUpload: { scope: '[data-bl=\"photo-upload\"]', slots: ['photo', 'thumb', 'remove'] },\n quoteForm: { scope: '[data-bl=\"quote-form\"] [data-bl=\"photo-upload\"]', slots: ['photo', 'thumb', 'remove'] },\n // Primitives rendered once per list entry (3.14.0): every part is repeated, the root included (style the root\n // through its own hook, `[data-bl=\"card\"]`).\n card: { scope: '[data-bl=\"card\"]', slots: ['media', 'body', 'title', 'link', 'text', 'meta'] },\n badge: { scope: '[data-bl=\"badge\"]', slots: ['icon', 'label'] },\n chip: { scope: '[data-bl=\"chip\"]', slots: ['icon', 'label'] },\n stat: { scope: '[data-bl=\"stat\"]', slots: ['value', 'label', 'link'] },\n tickList: { scope: '[data-bl=\"tick-list\"]', slots: ['item', 'tick', 'text', 'link'] },\n /** A lean list (cost item 1f): plain `<li><a>` entries with no `data-slot`, reached by element. */\n linkList: { scope: '[data-bl=\"link-list\"]', slots: ['item', 'link'], hooks: { item: '> li', link: '> li > a' } },\n} as const\n\nexport type RepeatedSlotComponent = keyof typeof REPEATED_SLOTS\n/** The repeated slots of one component, for example `RepeatedSlotOf<'siteFooter'>` is `'licenceLink' | … | 'policyLink'`. */\nexport type RepeatedSlotOf<Component extends RepeatedSlotComponent> = (typeof REPEATED_SLOTS)[Component]['slots'][number]\n\n/** The selector a skin stylesheet uses for one repeated slot, for example `[data-bl=\"footer\"] [data-slot=\"link\"]`. */\nexport function repeatedSlotSelector<Component extends RepeatedSlotComponent>(component: Component, slot: RepeatedSlotOf<Component>): string {\n const entry: { readonly scope: string; readonly hooks?: Readonly<Record<string, string>> } = REPEATED_SLOTS[component]\n return `${entry.scope} ${entry.hooks?.[slot] ?? `[data-slot=\"${slot}\"]`}`\n}\n"]}
@@ -10,6 +10,10 @@
10
10
  *
11
11
  * Placement (S8): on every page except contact, thank-you and 404, which already end in the form or a confirmation.
12
12
  * One variant per site, recorded in the skin.
13
+ *
14
+ * 3.16.0: an optional `eyebrow` above the heading; `layout.arrangement: 'split'` puts the heading and summary on one
15
+ * side and the actions on the other from 768 px; and the band's colour comes from the skin's `--bl-color-cta` (falling
16
+ * back to `--bl-color-band`), so a site sets its closing band apart from the footer.
13
17
  */
14
18
  import type { ReactNode } from 'react';
15
19
  import type { ButtonVariant } from '../primitives/links.js';
@@ -18,19 +22,23 @@ import { type SkinEntry } from '../skin.js';
18
22
  import type { UiPhone } from '../types.js';
19
23
  export declare const CTA_BAND_VARIANTS: readonly ["plain", "photo", "form"];
20
24
  export type CTABandVariant = (typeof CTA_BAND_VARIANTS)[number];
21
- export type CTABandSlot = 'root' | 'media' | 'inner' | 'content' | 'heading' | 'summary' | 'actions' | 'quote' | 'phone' | 'form';
25
+ export type CTABandSlot = 'root' | 'media' | 'inner' | 'content' | 'eyebrow' | 'heading' | 'summary' | 'actions' | 'quote' | 'phone' | 'form';
22
26
  export interface CTABandLayout {
23
27
  readonly align?: 'start' | 'center';
24
28
  /** The quote button's variant (default `primary`). */
25
29
  readonly quoteVariant?: ButtonVariant;
26
30
  /** The phone link's variant (default `button`). */
27
31
  readonly phoneVariant?: 'text' | 'button';
32
+ /** `stacked` (the default) or `split`: the words on one side, the actions on the other (3.16.0). */
33
+ readonly arrangement?: 'stacked' | 'split';
28
34
  }
29
35
  export type CTABandSkin = SkinEntry<CTABandSlot, CTABandVariant, CTABandLayout>;
30
36
  export declare const CTA_BAND_HEADING_ID = "bl-cta-heading";
31
37
  export interface CTABandProps extends CTABandSkin {
32
38
  /** The H2 text the site owns. */
33
39
  readonly heading: string;
40
+ /** A short label above the heading (3.16.0). */
41
+ readonly eyebrow?: string;
34
42
  /** One line under the heading. */
35
43
  readonly summary?: string;
36
44
  /**
@@ -55,5 +63,5 @@ export interface CTABandProps extends CTABandSkin {
55
63
  /** Signature art, rendered `aria-hidden`. */
56
64
  readonly decoration?: ReactNode;
57
65
  }
58
- export declare function CTABand({ heading, summary, quote, phone, phoneLabel, media, form, headingId, tone, decoration, variant, layout, classes, }: CTABandProps): import("react/jsx-runtime").JSX.Element;
66
+ export declare function CTABand({ heading, eyebrow, summary, quote, phone, phoneLabel, media, form, headingId, tone, decoration, variant, layout, classes, }: CTABandProps): import("react/jsx-runtime").JSX.Element;
59
67
  //# sourceMappingURL=cta-band.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cta-band.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/sections/cta-band.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,eAAO,MAAM,iBAAiB,qCAAsC,CAAA;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AAEjI,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IACnC,sDAAsD;IACtD,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAA;IACrC,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;CAC1C;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AAE/E,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,kCAAkC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAA;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;CAChC;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,OAAO,EACP,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,IAAI,EACJ,SAA+B,EAC/B,IAAI,EACJ,UAAU,EACV,OAAiB,EACjB,MAAM,EACN,OAAO,GACR,EAAE,YAAY,2CA6Cd"}
1
+ {"version":3,"file":"cta-band.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/sections/cta-band.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAE1C,eAAO,MAAM,iBAAiB,qCAAsC,CAAA;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AAE7I,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAA;IACnC,sDAAsD;IACtD,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAA;IACrC,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IACzC,oGAAoG;IACpG,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;CAC3C;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AAE/E,eAAO,MAAM,mBAAmB,mBAAmB,CAAA;AAEnD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,iCAAiC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,gDAAgD;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,kCAAkC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAA;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;CAChC;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,IAAI,EACJ,SAA+B,EAC/B,IAAI,EACJ,UAAU,EACV,OAAiB,EACjB,MAAM,EACN,OAAO,GACR,EAAE,YAAY,2CA+Cd"}
@@ -4,8 +4,8 @@ import { QuoteButton } from '../primitives/quote-button.js';
4
4
  import { slot } from '../skin.js';
5
5
  export const CTA_BAND_VARIANTS = ['plain', 'photo', 'form'];
6
6
  export const CTA_BAND_HEADING_ID = 'bl-cta-heading';
7
- export function CTABand({ heading, summary, quote, phone, phoneLabel, media, form, headingId = CTA_BAND_HEADING_ID, tone, decoration, variant = 'plain', layout, classes, }) {
7
+ export function CTABand({ heading, eyebrow, summary, quote, phone, phoneLabel, media, form, headingId = CTA_BAND_HEADING_ID, tone, decoration, variant = 'plain', layout, classes, }) {
8
8
  const shown = (variant === 'photo' && !media) || (variant === 'form' && !form) ? 'plain' : variant;
9
- return (_jsxs("section", { "data-bl-section": "cta", "data-variant": shown, "data-tone": tone ?? (shown === 'photo' ? 'photo' : undefined), "data-align": layout?.align ?? 'start', "aria-labelledby": headingId, className: classes?.root, children: [decoration ? (_jsx("div", { "data-slot": "decoration", "aria-hidden": "true", children: decoration })) : null, shown === 'photo' ? (_jsx("div", { ...slot(classes, 'media'), "aria-hidden": "true", children: media })) : null, _jsxs("div", { ...slot(classes, 'inner'), children: [_jsxs("div", { ...slot(classes, 'content'), children: [_jsx("h2", { id: headingId, ...slot(classes, 'heading'), children: heading }), summary ? _jsx("p", { ...slot(classes, 'summary'), children: summary }) : null, _jsxs("div", { ...slot(classes, 'actions'), children: [_jsx(PhoneLink, { phone: phone, placement: "cta", label: phoneLabel, showIcon: true, variant: layout?.phoneVariant ?? 'button', classes: { root: classes?.phone } }), shown === 'form' || !quote ? null : (_jsx(QuoteButton, { label: quote.label, href: quote.href, placement: "section", ctaId: "quote-cta", variant: layout?.quoteVariant ?? 'primary', classes: { root: classes?.quote } }))] })] }), shown === 'form' ? _jsx("div", { ...slot(classes, 'form'), children: form }) : null] })] }));
9
+ return (_jsxs("section", { "data-bl-section": "cta", "data-variant": shown, "data-tone": tone ?? (shown === 'photo' ? 'photo' : undefined), "data-align": layout?.align ?? 'start', "data-arrangement": layout?.arrangement === 'split' && shown !== 'form' ? 'split' : undefined, "aria-labelledby": headingId, className: classes?.root, children: [decoration ? (_jsx("div", { "data-slot": "decoration", "aria-hidden": "true", children: decoration })) : null, shown === 'photo' ? (_jsx("div", { ...slot(classes, 'media'), "aria-hidden": "true", children: media })) : null, _jsxs("div", { ...slot(classes, 'inner'), children: [_jsxs("div", { ...slot(classes, 'content'), children: [eyebrow ? _jsx("p", { ...slot(classes, 'eyebrow'), children: eyebrow }) : null, _jsx("h2", { id: headingId, ...slot(classes, 'heading'), children: heading }), summary ? _jsx("p", { ...slot(classes, 'summary'), children: summary }) : null, _jsxs("div", { ...slot(classes, 'actions'), children: [_jsx(PhoneLink, { phone: phone, placement: "cta", label: phoneLabel, showIcon: true, variant: layout?.phoneVariant ?? 'button', classes: { root: classes?.phone } }), shown === 'form' || !quote ? null : (_jsx(QuoteButton, { label: quote.label, href: quote.href, placement: "section", ctaId: "quote-cta", variant: layout?.quoteVariant ?? 'primary', classes: { root: classes?.quote } }))] })] }), shown === 'form' ? _jsx("div", { ...slot(classes, 'form'), children: form }) : null] })] }));
10
10
  }
11
11
  //# sourceMappingURL=cta-band.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cta-band.js","sourceRoot":"","sources":["../../../src/ui-kit/sections/cta-band.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAC3D,OAAO,EAAE,IAAI,EAAkB,MAAM,YAAY,CAAA;AAGjD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAU,CAAA;AAepE,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAA;AA2BnD,MAAM,UAAU,OAAO,CAAC,EACtB,OAAO,EACP,OAAO,EACP,KAAK,EACL,KAAK,EACL,UAAU,EACV,KAAK,EACL,IAAI,EACJ,SAAS,GAAG,mBAAmB,EAC/B,IAAI,EACJ,UAAU,EACV,OAAO,GAAG,OAAO,EACjB,MAAM,EACN,OAAO,GACM;IACb,MAAM,KAAK,GAAmB,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAA;IAClH,OAAO,CACL,sCACkB,KAAK,kBACP,KAAK,eACR,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,gBAChD,MAAM,EAAE,KAAK,IAAI,OAAO,qBACnB,SAAS,EAC1B,SAAS,EAAE,OAAO,EAAE,IAAI,aAEvB,UAAU,CAAC,CAAC,CAAC,CACZ,2BAAe,YAAY,iBAAa,MAAM,YAC3C,UAAU,GACP,CACP,CAAC,CAAC,CAAC,IAAI,EACP,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,CACnB,iBAAS,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAc,MAAM,YAChD,KAAK,GACF,CACP,CAAC,CAAC,CAAC,IAAI,EACR,kBAAS,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,aAC7B,kBAAS,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,aAC/B,aAAI,EAAE,EAAE,SAAS,KAAM,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAC5C,OAAO,GACL,EACJ,OAAO,CAAC,CAAC,CAAC,eAAO,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,YAAG,OAAO,GAAK,CAAC,CAAC,CAAC,IAAI,EAChE,kBAAS,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,aAC/B,KAAC,SAAS,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAC,KAAK,EAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,QAAC,OAAO,EAAE,MAAM,EAAE,YAAY,IAAI,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAI,EACpJ,KAAK,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACnC,KAAC,WAAW,IACV,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,IAAI,EAAE,KAAK,CAAC,IAAI,EAChB,SAAS,EAAC,SAAS,EACnB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAE,MAAM,EAAE,YAAY,IAAI,SAAS,EAC1C,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GACjC,CACH,IACG,IACF,EACL,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAS,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,YAAG,IAAI,GAAO,CAAC,CAAC,CAAC,IAAI,IACnE,IACE,CACX,CAAA;AACH,CAAC","sourcesContent":["/**\n * S8 `CTABand` (`cta`): the one closing action design a site uses on every page. Server component, no client JS of\n * its own. A heading, an optional one-line summary, the quote button (`lead_cta_click` placement `section`, id\n * `quote-cta`) and one phone link (`phone_link_click` placement `cta`), phone first like the header, hero and call bar. No \"what happens next\" filler.\n *\n * Variants: `plain`; `photo`, with the site's backdrop image in `media` (decorative, so it renders `aria-hidden`);\n * `form`, with the site's own quote form in `form` beside the heading and the phone link (the form is the quote\n * action there, so the quote button is left out). A `photo` band without `media` or a `form` band without `form`\n * renders as `plain`.\n *\n * Placement (S8): on every page except contact, thank-you and 404, which already end in the form or a confirmation.\n * One variant per site, recorded in the skin.\n */\nimport type { ReactNode } from 'react'\nimport { PhoneLink } from '../primitives/links.js'\nimport type { ButtonVariant } from '../primitives/links.js'\nimport type { SectionTone } from '../primitives/layout.js'\nimport { QuoteButton } from '../primitives/quote-button.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\n\nexport const CTA_BAND_VARIANTS = ['plain', 'photo', 'form'] as const\nexport type CTABandVariant = (typeof CTA_BAND_VARIANTS)[number]\n\nexport type CTABandSlot = 'root' | 'media' | 'inner' | 'content' | 'heading' | 'summary' | 'actions' | 'quote' | 'phone' | 'form'\n\nexport interface CTABandLayout {\n readonly align?: 'start' | 'center'\n /** The quote button's variant (default `primary`). */\n readonly quoteVariant?: ButtonVariant\n /** The phone link's variant (default `button`). */\n readonly phoneVariant?: 'text' | 'button'\n}\n\nexport type CTABandSkin = SkinEntry<CTABandSlot, CTABandVariant, CTABandLayout>\n\nexport const CTA_BAND_HEADING_ID = 'bl-cta-heading'\n\nexport interface CTABandProps extends CTABandSkin {\n /** The H2 text the site owns. */\n readonly heading: string\n /** One line under the heading. */\n readonly summary?: string\n /**\n * The site's recorded quote label (C5) and the quote form it falls back to, for example `/contact#quote`. Required\n * for the `plain` and `photo` variants; the `form` variant leaves the quote button out, so it may omit this.\n */\n readonly quote?: { readonly label: string; readonly href: string }\n readonly phone: UiPhone\n /** Optional words before the number, for example \"Call\". */\n readonly phoneLabel?: string\n /** The `photo` variant's backdrop: the site's image node (decorative). */\n readonly media?: ReactNode\n /** The `form` variant's form: the site's own quote form. */\n readonly form?: ReactNode\n /** The id of the band's H2 (default `bl-cta-heading`). */\n readonly headingId?: string\n /** Set by `SectionSequence`; a `photo` band defaults to `photo`. */\n readonly tone?: SectionTone\n /** Signature art, rendered `aria-hidden`. */\n readonly decoration?: ReactNode\n}\n\nexport function CTABand({\n heading,\n summary,\n quote,\n phone,\n phoneLabel,\n media,\n form,\n headingId = CTA_BAND_HEADING_ID,\n tone,\n decoration,\n variant = 'plain',\n layout,\n classes,\n}: CTABandProps) {\n const shown: CTABandVariant = (variant === 'photo' && !media) || (variant === 'form' && !form) ? 'plain' : variant\n return (\n <section\n data-bl-section=\"cta\"\n data-variant={shown}\n data-tone={tone ?? (shown === 'photo' ? 'photo' : undefined)}\n data-align={layout?.align ?? 'start'}\n aria-labelledby={headingId}\n className={classes?.root}\n >\n {decoration ? (\n <div data-slot=\"decoration\" aria-hidden=\"true\">\n {decoration}\n </div>\n ) : null}\n {shown === 'photo' ? (\n <div {...slot(classes, 'media')} aria-hidden=\"true\">\n {media}\n </div>\n ) : null}\n <div {...slot(classes, 'inner')}>\n <div {...slot(classes, 'content')}>\n <h2 id={headingId} {...slot(classes, 'heading')}>\n {heading}\n </h2>\n {summary ? <p {...slot(classes, 'summary')}>{summary}</p> : null}\n <div {...slot(classes, 'actions')}>\n <PhoneLink phone={phone} placement=\"cta\" label={phoneLabel} showIcon variant={layout?.phoneVariant ?? 'button'} classes={{ root: classes?.phone }} />\n {shown === 'form' || !quote ? null : (\n <QuoteButton\n label={quote.label}\n href={quote.href}\n placement=\"section\"\n ctaId=\"quote-cta\"\n variant={layout?.quoteVariant ?? 'primary'}\n classes={{ root: classes?.quote }}\n />\n )}\n </div>\n </div>\n {shown === 'form' ? <div {...slot(classes, 'form')}>{form}</div> : null}\n </div>\n </section>\n )\n}\n"]}
1
+ {"version":3,"file":"cta-band.js","sourceRoot":"","sources":["../../../src/ui-kit/sections/cta-band.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * S8 `CTABand` (`cta`): the one closing action design a site uses on every page. Server component, no client JS of\n * its own. A heading, an optional one-line summary, the quote button (`lead_cta_click` placement `section`, id\n * `quote-cta`) and one phone link (`phone_link_click` placement `cta`), phone first like the header, hero and call bar. No \"what happens next\" filler.\n *\n * Variants: `plain`; `photo`, with the site's backdrop image in `media` (decorative, so it renders `aria-hidden`);\n * `form`, with the site's own quote form in `form` beside the heading and the phone link (the form is the quote\n * action there, so the quote button is left out). A `photo` band without `media` or a `form` band without `form`\n * renders as `plain`.\n *\n * Placement (S8): on every page except contact, thank-you and 404, which already end in the form or a confirmation.\n * One variant per site, recorded in the skin.\n *\n * 3.16.0: an optional `eyebrow` above the heading; `layout.arrangement: 'split'` puts the heading and summary on one\n * side and the actions on the other from 768 px; and the band's colour comes from the skin's `--bl-color-cta` (falling\n * back to `--bl-color-band`), so a site sets its closing band apart from the footer.\n */\nimport type { ReactNode } from 'react'\nimport { PhoneLink } from '../primitives/links.js'\nimport type { ButtonVariant } from '../primitives/links.js'\nimport type { SectionTone } from '../primitives/layout.js'\nimport { QuoteButton } from '../primitives/quote-button.js'\nimport { slot, type SkinEntry } from '../skin.js'\nimport type { UiPhone } from '../types.js'\n\nexport const CTA_BAND_VARIANTS = ['plain', 'photo', 'form'] as const\nexport type CTABandVariant = (typeof CTA_BAND_VARIANTS)[number]\n\nexport type CTABandSlot = 'root' | 'media' | 'inner' | 'content' | 'eyebrow' | 'heading' | 'summary' | 'actions' | 'quote' | 'phone' | 'form'\n\nexport interface CTABandLayout {\n readonly align?: 'start' | 'center'\n /** The quote button's variant (default `primary`). */\n readonly quoteVariant?: ButtonVariant\n /** The phone link's variant (default `button`). */\n readonly phoneVariant?: 'text' | 'button'\n /** `stacked` (the default) or `split`: the words on one side, the actions on the other (3.16.0). */\n readonly arrangement?: 'stacked' | 'split'\n}\n\nexport type CTABandSkin = SkinEntry<CTABandSlot, CTABandVariant, CTABandLayout>\n\nexport const CTA_BAND_HEADING_ID = 'bl-cta-heading'\n\nexport interface CTABandProps extends CTABandSkin {\n /** The H2 text the site owns. */\n readonly heading: string\n /** A short label above the heading (3.16.0). */\n readonly eyebrow?: string\n /** One line under the heading. */\n readonly summary?: string\n /**\n * The site's recorded quote label (C5) and the quote form it falls back to, for example `/contact#quote`. Required\n * for the `plain` and `photo` variants; the `form` variant leaves the quote button out, so it may omit this.\n */\n readonly quote?: { readonly label: string; readonly href: string }\n readonly phone: UiPhone\n /** Optional words before the number, for example \"Call\". */\n readonly phoneLabel?: string\n /** The `photo` variant's backdrop: the site's image node (decorative). */\n readonly media?: ReactNode\n /** The `form` variant's form: the site's own quote form. */\n readonly form?: ReactNode\n /** The id of the band's H2 (default `bl-cta-heading`). */\n readonly headingId?: string\n /** Set by `SectionSequence`; a `photo` band defaults to `photo`. */\n readonly tone?: SectionTone\n /** Signature art, rendered `aria-hidden`. */\n readonly decoration?: ReactNode\n}\n\nexport function CTABand({\n heading,\n eyebrow,\n summary,\n quote,\n phone,\n phoneLabel,\n media,\n form,\n headingId = CTA_BAND_HEADING_ID,\n tone,\n decoration,\n variant = 'plain',\n layout,\n classes,\n}: CTABandProps) {\n const shown: CTABandVariant = (variant === 'photo' && !media) || (variant === 'form' && !form) ? 'plain' : variant\n return (\n <section\n data-bl-section=\"cta\"\n data-variant={shown}\n data-tone={tone ?? (shown === 'photo' ? 'photo' : undefined)}\n data-align={layout?.align ?? 'start'}\n data-arrangement={layout?.arrangement === 'split' && shown !== 'form' ? 'split' : undefined}\n aria-labelledby={headingId}\n className={classes?.root}\n >\n {decoration ? (\n <div data-slot=\"decoration\" aria-hidden=\"true\">\n {decoration}\n </div>\n ) : null}\n {shown === 'photo' ? (\n <div {...slot(classes, 'media')} aria-hidden=\"true\">\n {media}\n </div>\n ) : null}\n <div {...slot(classes, 'inner')}>\n <div {...slot(classes, 'content')}>\n {eyebrow ? <p {...slot(classes, 'eyebrow')}>{eyebrow}</p> : null}\n <h2 id={headingId} {...slot(classes, 'heading')}>\n {heading}\n </h2>\n {summary ? <p {...slot(classes, 'summary')}>{summary}</p> : null}\n <div {...slot(classes, 'actions')}>\n <PhoneLink phone={phone} placement=\"cta\" label={phoneLabel} showIcon variant={layout?.phoneVariant ?? 'button'} classes={{ root: classes?.phone }} />\n {shown === 'form' || !quote ? null : (\n <QuoteButton\n label={quote.label}\n href={quote.href}\n placement=\"section\"\n ctaId=\"quote-cta\"\n variant={layout?.quoteVariant ?? 'primary'}\n classes={{ root: classes?.quote }}\n />\n )}\n </div>\n </div>\n {shown === 'form' ? <div {...slot(classes, 'form')}>{form}</div> : null}\n </div>\n </section>\n )\n}\n"]}
@@ -23,8 +23,21 @@
23
23
  * `family` is the page family (`data-family`): `home` takes no breadcrumbs and is `tall` by default; `service` and
24
24
  * `location` take breadcrumbs. A skin styles families apart through `[data-family]`; the variant is the site's one
25
25
  * hero structure.
26
+ *
27
+ * The site's own hero (3.16.0), inside the same skeleton:
28
+ * - `layout.contentOrder` arranges the text column's parts (AA: H1, rating, summary, checklist, actions). The
29
+ * breadcrumbs stay first, an eyebrow sits straight before the H1, and the H1 comes before the summary and actions;
30
+ * parts left out follow in the default order;
31
+ * - `layout.rating: 'figure'` shows Google's rating as a large figure with the stars and count, and `ratingMoreLabel`
32
+ * adds the site's link to all the reviews;
33
+ * - `formHeading` puts an eyebrow, an H2 and a line above the quote form (the hero's one H2);
34
+ * - `seal` stamps one verified fact on the photo (`{ value: '15+', label: 'years of tree work' }`);
35
+ * - `layout.scrim` chooses the overlay: `full` over the whole photo, `column` behind the text side only, or `none`
36
+ * (the default on `split`; `full-bleed` defaults to `full`), coloured by the skin's `--bl-hero-scrim`;
37
+ * - the photo's corners, shadow and filter come from `--bl-hero-photo-radius`, `--bl-hero-photo-shadow` and
38
+ * `--bl-hero-photo-filter`, and the `decoration` slot holds the site's motif.
26
39
  */
27
- import type { ReactNode } from 'react';
40
+ import { type ReactNode } from 'react';
28
41
  import { type SiteJobMode } from '@brandlab-digital/site-core/strategy';
29
42
  import { type SectionTone } from '../primitives/layout.js';
30
43
  import { type TickItem } from '../primitives/lists.js';
@@ -32,6 +45,11 @@ import { type UiMedia } from '../primitives/media-frame.js';
32
45
  import { type SkinEntry } from '../skin.js';
33
46
  import type { UiPhone } from '../types.js';
34
47
  import { type RatingChipData } from './rating-chip.js';
48
+ /** The text column's parts, in their default order (3.16.0). The breadcrumbs always come first. */
49
+ export declare const HERO_CONTENT_PARTS: readonly ["eyebrow", "h1", "summary", "actions", "checklist", "rating", "badges"];
50
+ export type HeroContentPart = (typeof HERO_CONTENT_PARTS)[number];
51
+ export declare const HERO_SCRIMS: readonly ["none", "full", "column"];
52
+ export type HeroScrim = (typeof HERO_SCRIMS)[number];
35
53
  export declare const HERO_VARIANTS: readonly ["split", "full-bleed"];
36
54
  export type HeroVariant = (typeof HERO_VARIANTS)[number];
37
55
  /**
@@ -46,7 +64,7 @@ export type HeroFamily = (typeof HERO_FAMILIES)[number];
46
64
  */
47
65
  export declare const HERO_JOB_MODES: readonly ["urgent", "planned", "mixed"];
48
66
  export type HeroJobMode = SiteJobMode;
49
- export type HeroSlot = 'root' | 'inner' | 'content' | 'crumbs' | 'eyebrow' | 'h1' | 'summary' | 'actions' | 'phone' | 'quote' | 'checklist' | 'rating' | 'badges' | 'media' | 'caption' | 'scrim' | 'form';
67
+ export type HeroSlot = 'root' | 'inner' | 'content' | 'crumbs' | 'eyebrow' | 'h1' | 'summary' | 'actions' | 'phone' | 'quote' | 'checklist' | 'rating' | 'badges' | 'media' | 'caption' | 'scrim' | 'form' | 'formHead' | 'formEyebrow' | 'formTitle' | 'formText' | 'seal' | 'sealValue' | 'sealLabel';
50
68
  export interface HeroLayout {
51
69
  /** `split`: the photo's side on desktop (default `end`). */
52
70
  readonly mediaSide?: 'start' | 'end';
@@ -59,6 +77,12 @@ export interface HeroLayout {
59
77
  * stylesheet draws as a short rule (`TickList`'s `layout.tick`), about 100 bytes less a fact.
60
78
  */
61
79
  readonly checklistTick?: 'icon' | 'rule';
80
+ /** The text column's order (3.16.0); parts left out follow in the default order. */
81
+ readonly contentOrder?: readonly HeroContentPart[];
82
+ /** Google's rating as one line (`chip`, the default) or a large figure with the stars and count (3.16.0). */
83
+ readonly rating?: 'chip' | 'figure';
84
+ /** The photo's overlay (3.16.0): `full`, `column` (behind the text side only) or `none`. */
85
+ readonly scrim?: HeroScrim;
62
86
  }
63
87
  export type HeroSkin = SkinEntry<HeroSlot, HeroVariant, HeroLayout>;
64
88
  /** The form's id and lead diagnostics `form_id` in the hero; the quote button links here. */
@@ -113,6 +137,23 @@ export interface HeroProps extends HeroSkin {
113
137
  readonly tone?: SectionTone;
114
138
  /** Signature art, rendered `aria-hidden` (Superior's waterline, Absolute's grass edge). */
115
139
  readonly decoration?: ReactNode;
140
+ /** The site's words for a link to all the reviews on Google, after the rating (3.16.0). */
141
+ readonly ratingMoreLabel?: string;
142
+ /** A heading block above the quote form (3.16.0): an optional eyebrow, the H2 and an optional line. */
143
+ readonly formHeading?: {
144
+ readonly eyebrow?: string;
145
+ readonly title: string;
146
+ readonly text?: string;
147
+ };
148
+ /** One verified fact stamped on the photo (3.16.0), for example `{ value: '15+', label: 'years of tree work' }`. */
149
+ readonly seal?: {
150
+ readonly value: string;
151
+ readonly label: string;
152
+ };
116
153
  }
154
+ /** The form heading's id (3.16.0). */
155
+ export declare const HERO_FORM_HEADING_ID = "quote-hero-title";
156
+ /** The text column's order: the site's order, then the parts it left out in the default order. */
157
+ export declare function heroContentOrder(order?: readonly HeroContentPart[]): HeroContentPart[];
117
158
  export declare function Hero(props: HeroProps): import("react/jsx-runtime").JSX.Element;
118
159
  //# sourceMappingURL=hero.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/sections/hero.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hero.d.ts","sourceRoot":"","sources":["../../../src/ui-kit/sections/hero.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,sCAAsC,CAAA;AACvF,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAEnE,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,8BAA8B,CAAA;AAEvE,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,YAAY,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEnF,mGAAmG;AACnG,eAAO,MAAM,kBAAkB,mFAAoF,CAAA;AACnH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjE,eAAO,MAAM,WAAW,qCAAsC,CAAA;AAC9D,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,aAAa,kCAAmC,CAAA;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD;;;GAGG;AACH,eAAO,MAAM,aAAa,0CAA2C,CAAA;AACrE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvD;;;GAGG;AACH,eAAO,MAAM,cAAc,yCAAiB,CAAA;AAC5C,MAAM,MAAM,WAAW,GAAG,WAAW,CAAA;AAErC,MAAM,MAAM,QAAQ,GAChB,MAAM,GACN,OAAO,GACP,SAAS,GACT,QAAQ,GACR,SAAS,GACT,IAAI,GACJ,SAAS,GACT,SAAS,GACT,OAAO,GACP,OAAO,GACP,WAAW,GACX,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,SAAS,GACT,OAAO,GACP,MAAM,GACN,UAAU,GACV,aAAa,GACb,WAAW,GACX,UAAU,GACV,MAAM,GACN,WAAW,GACX,WAAW,CAAA;AAEf,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IACpC,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IACrC,iDAAiD;IACjD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACjC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxC,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAClD,6GAA6G;IAC7G,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IACnC,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAA;CAC3B;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAA;AAEnE,6FAA6F;AAC7F,eAAO,MAAM,YAAY,eAAe,CAAA;AACxC,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,IAAI,CAAA;AACnC,6CAA6C;AAC7C,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAExC,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,gHAAgH;IAChH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,kCAAkC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,8GAA8G;IAC9G,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAA;IAChC,wGAAwG;IACxG,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAA;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,CAAA;IACvC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;IAC3B,4GAA4G;IAC5G,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,gGAAgG;IAChG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAClE,sGAAsG;IACtG,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;IACzB,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAA;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,gCAAgC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAA;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAA;IAC/B,2FAA2F;IAC3F,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,uGAAuG;IACvG,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACpG,oHAAoH;IACpH,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACnE;AAED,sCAAsC;AACtC,eAAO,MAAM,oBAAoB,qBAA0B,CAAA;AAE3D,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,SAAS,eAAe,EAAO,GAAG,eAAe,EAAE,CAc1F;AAkBD,wBAAgB,IAAI,CAAC,KAAK,EAAE,SAAS,2CA4HpC"}