@brandlab-digital/site-next 3.15.0 → 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.
- package/dist/image-runtime.js +6 -1
- package/dist/image-runtime.js.map +1 -1
- package/dist/navigation/use-sticky-call-bar.d.ts +6 -1
- package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -1
- package/dist/navigation/use-sticky-call-bar.js +9 -4
- package/dist/navigation/use-sticky-call-bar.js.map +1 -1
- package/dist/next-sharp.d.ts +14 -9
- package/dist/next-sharp.d.ts.map +1 -1
- package/dist/next-sharp.js +26 -25
- package/dist/next-sharp.js.map +1 -1
- package/dist/ui-kit/brandlab-skin.d.ts +2 -0
- package/dist/ui-kit/brandlab-skin.d.ts.map +1 -1
- package/dist/ui-kit/brandlab-skin.js.map +1 -1
- package/dist/ui-kit/repeated-slots.d.ts +1 -1
- package/dist/ui-kit/repeated-slots.js +1 -1
- package/dist/ui-kit/repeated-slots.js.map +1 -1
- package/dist/ui-kit/sections/cta-band.d.ts +10 -2
- package/dist/ui-kit/sections/cta-band.d.ts.map +1 -1
- package/dist/ui-kit/sections/cta-band.js +2 -2
- package/dist/ui-kit/sections/cta-band.js.map +1 -1
- package/dist/ui-kit/sections/hero.d.ts +43 -2
- package/dist/ui-kit/sections/hero.d.ts.map +1 -1
- package/dist/ui-kit/sections/hero.js +86 -3
- package/dist/ui-kit/sections/hero.js.map +1 -1
- package/dist/ui-kit/sections/index.d.ts +3 -2
- package/dist/ui-kit/sections/index.d.ts.map +1 -1
- package/dist/ui-kit/sections/index.js +3 -2
- package/dist/ui-kit/sections/index.js.map +1 -1
- package/dist/ui-kit/sections/proof-strip.d.ts +7 -1
- package/dist/ui-kit/sections/proof-strip.d.ts.map +1 -1
- package/dist/ui-kit/sections/proof-strip.js +6 -2
- package/dist/ui-kit/sections/proof-strip.js.map +1 -1
- package/dist/ui-kit/sections/rating-chip.d.ts +15 -5
- package/dist/ui-kit/sections/rating-chip.d.ts.map +1 -1
- package/dist/ui-kit/sections/rating-chip.js +10 -4
- package/dist/ui-kit/sections/rating-chip.js.map +1 -1
- package/dist/ui-kit/sections/section-sequence.d.ts +3 -1
- package/dist/ui-kit/sections/section-sequence.d.ts.map +1 -1
- package/dist/ui-kit/sections/section-sequence.js +4 -2
- package/dist/ui-kit/sections/section-sequence.js.map +1 -1
- package/dist/ui-kit/sections/signature-section.d.ts +42 -0
- package/dist/ui-kit/sections/signature-section.d.ts.map +1 -0
- package/dist/ui-kit/sections/signature-section.js +14 -0
- package/dist/ui-kit/sections/signature-section.js.map +1 -0
- package/dist/ui-kit/shell/call-bar-client.d.ts +2 -1
- package/dist/ui-kit/shell/call-bar-client.d.ts.map +1 -1
- package/dist/ui-kit/shell/call-bar-client.js +3 -3
- package/dist/ui-kit/shell/call-bar-client.js.map +1 -1
- package/dist/ui-kit/shell/mobile-call-bar.d.ts +6 -2
- package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -1
- package/dist/ui-kit/shell/mobile-call-bar.js +5 -2
- package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -1
- package/dist/ui-kit/structure.css +137 -2
- package/package.json +2 -2
package/dist/image-runtime.js
CHANGED
|
@@ -5,7 +5,12 @@ import { findNextGetSharp } from './next-sharp.js';
|
|
|
5
5
|
// that cache before applying our exclusion, without patching either library.
|
|
6
6
|
// This private Next entrypoint is covered by the exact runtime pin and packed
|
|
7
7
|
// startup-order tests. Remove this bridge when maintained native fixes ship.
|
|
8
|
-
|
|
8
|
+
//
|
|
9
|
+
// Keep the require below a literal path on this module's createRequire: Next's
|
|
10
|
+
// output tracing only deploys the file with the route when it can see the path
|
|
11
|
+
// (3.15.1). The golden fixtures check the contact route's trace lists it.
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
const getSharp = findNextGetSharp(() => require.resolve('next/package.json'), () => require('next/dist/server/image-optimizer/transform.js'));
|
|
9
14
|
getSharp?.();
|
|
10
15
|
sharp.block({ operation: ['VipsForeignLoadHeif'] });
|
|
11
16
|
//# sourceMappingURL=image-runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-runtime.js","sourceRoot":"","sources":["../src/image-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAElD,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,MAAM,QAAQ,GAAG,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"image-runtime.js","sourceRoot":"","sources":["../src/image-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAElD,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC9C,MAAM,QAAQ,GAAG,gBAAgB,CAC/B,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAC1C,GAAG,EAAE,CAAC,OAAO,CAAC,+CAA+C,CAAC,CAC/D,CAAA;AACD,QAAQ,EAAE,EAAE,CAAA;AACZ,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAA","sourcesContent":["import { createRequire } from 'node:module'\nimport sharp from 'sharp'\nimport { findNextGetSharp } from './next-sharp.js'\n\n// Next lazily unblocks HEIF when its optimizer first acquires Sharp. Initialise\n// that cache before applying our exclusion, without patching either library.\n// This private Next entrypoint is covered by the exact runtime pin and packed\n// startup-order tests. Remove this bridge when maintained native fixes ship.\n//\n// Keep the require below a literal path on this module's createRequire: Next's\n// output tracing only deploys the file with the route when it can see the path\n// (3.15.1). The golden fixtures check the contact route's trace lists it.\nconst require = createRequire(import.meta.url)\nconst getSharp = findNextGetSharp(\n () => require.resolve('next/package.json'),\n () => require('next/dist/server/image-optimizer/transform.js'),\n)\ngetSharp?.()\nsharp.block({ operation: ['VipsForeignLoadHeif'] })\n"]}
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
-
|
|
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":"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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 *\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"]}
|
package/dist/next-sharp.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Next
|
|
3
|
-
* `next/dist/server/image-optimizer.js` to `next/dist/server/image-optimizer/transform.js
|
|
4
|
-
* before blocking the HEIF decoder, because Next unblocks HEIF the first time its optimiser acquires Sharp.
|
|
2
|
+
* The Next module that holds its private Sharp initialiser on the pinned Next release (16.4 moved `getSharp` from
|
|
3
|
+
* `next/dist/server/image-optimizer.js` to `next/dist/server/image-optimizer/transform.js`). The image runtime calls
|
|
4
|
+
* it before blocking the HEIF decoder, because Next unblocks HEIF the first time its optimiser acquires Sharp.
|
|
5
|
+
*
|
|
6
|
+
* The image runtime must load this module with a literal `require('next/dist/server/image-optimizer/transform.js')`
|
|
7
|
+
* on its own `createRequire(import.meta.url)`. Next's output tracing only copies a module into a deployed route
|
|
8
|
+
* when it sees a literal path there; a path held in a variable or passed through a helper is never traced, so the
|
|
9
|
+
* route fails on Vercel while it passes against a full local `node_modules` (3.12.1–3.15.0).
|
|
5
10
|
*/
|
|
6
|
-
export declare const
|
|
7
|
-
type ModuleRequire = (id: string) => unknown;
|
|
11
|
+
export declare const NEXT_SHARP_MODULE = "next/dist/server/image-optimizer/transform.js";
|
|
8
12
|
/**
|
|
9
|
-
* The installed Next's `getSharp`, or undefined when Next is not installed.
|
|
10
|
-
*
|
|
13
|
+
* The installed Next's `getSharp`, or undefined when Next is not installed. `resolveNext` resolves
|
|
14
|
+
* `next/package.json`; `loadTransform` is the image runtime's literal require of {@link NEXT_SHARP_MODULE}. Throws
|
|
15
|
+
* when Next is installed but the module cannot be loaded (keeping the original error as the cause) or exposes no
|
|
16
|
+
* `getSharp`, so the route fails at startup instead of leaving HEIF decoding open.
|
|
11
17
|
*/
|
|
12
|
-
export declare function findNextGetSharp(
|
|
13
|
-
export {};
|
|
18
|
+
export declare function findNextGetSharp(resolveNext: () => unknown, loadTransform: () => unknown): (() => unknown) | undefined;
|
|
14
19
|
//# sourceMappingURL=next-sharp.d.ts.map
|
package/dist/next-sharp.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-sharp.d.ts","sourceRoot":"","sources":["../src/next-sharp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"next-sharp.d.ts","sourceRoot":"","sources":["../src/next-sharp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,kDAAkD,CAAA;AAEhF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,OAAO,EAC1B,aAAa,EAAE,MAAM,OAAO,GAC3B,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,CAsB7B"}
|
package/dist/next-sharp.js
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Next
|
|
3
|
-
* `next/dist/server/image-optimizer.js` to `next/dist/server/image-optimizer/transform.js
|
|
4
|
-
* before blocking the HEIF decoder, because Next unblocks HEIF the first time its optimiser acquires Sharp.
|
|
2
|
+
* The Next module that holds its private Sharp initialiser on the pinned Next release (16.4 moved `getSharp` from
|
|
3
|
+
* `next/dist/server/image-optimizer.js` to `next/dist/server/image-optimizer/transform.js`). The image runtime calls
|
|
4
|
+
* it before blocking the HEIF decoder, because Next unblocks HEIF the first time its optimiser acquires Sharp.
|
|
5
|
+
*
|
|
6
|
+
* The image runtime must load this module with a literal `require('next/dist/server/image-optimizer/transform.js')`
|
|
7
|
+
* on its own `createRequire(import.meta.url)`. Next's output tracing only copies a module into a deployed route
|
|
8
|
+
* when it sees a literal path there; a path held in a variable or passed through a helper is never traced, so the
|
|
9
|
+
* route fails on Vercel while it passes against a full local `node_modules` (3.12.1–3.15.0).
|
|
5
10
|
*/
|
|
6
|
-
export const
|
|
7
|
-
'next/dist/server/image-optimizer/transform.js',
|
|
8
|
-
'next/dist/server/image-optimizer.js',
|
|
9
|
-
];
|
|
11
|
+
export const NEXT_SHARP_MODULE = 'next/dist/server/image-optimizer/transform.js';
|
|
10
12
|
/**
|
|
11
|
-
* The installed Next's `getSharp`, or undefined when Next is not installed.
|
|
12
|
-
*
|
|
13
|
+
* The installed Next's `getSharp`, or undefined when Next is not installed. `resolveNext` resolves
|
|
14
|
+
* `next/package.json`; `loadTransform` is the image runtime's literal require of {@link NEXT_SHARP_MODULE}. Throws
|
|
15
|
+
* when Next is installed but the module cannot be loaded (keeping the original error as the cause) or exposes no
|
|
16
|
+
* `getSharp`, so the route fails at startup instead of leaving HEIF decoding open.
|
|
13
17
|
*/
|
|
14
|
-
export function findNextGetSharp(
|
|
18
|
+
export function findNextGetSharp(resolveNext, loadTransform) {
|
|
15
19
|
try {
|
|
16
|
-
|
|
20
|
+
resolveNext();
|
|
17
21
|
}
|
|
18
22
|
catch (error) {
|
|
19
23
|
if (error.code === 'MODULE_NOT_FOUND')
|
|
20
24
|
return undefined;
|
|
21
25
|
throw error;
|
|
22
26
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
continue;
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
const getSharp = loaded?.getSharp;
|
|
34
|
-
if (typeof getSharp === 'function')
|
|
35
|
-
return getSharp;
|
|
27
|
+
let loaded;
|
|
28
|
+
try {
|
|
29
|
+
loaded = loadTransform();
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
33
|
+
throw new Error(`@brandlab-digital/site-next/image-runtime could not load ${NEXT_SHARP_MODULE} from the installed Next.js (${detail}), so it cannot keep HEIF decoding blocked. Use the Next.js version the Brandlab release pins, and check that the deployed route includes that file.`, { cause: error });
|
|
36
34
|
}
|
|
37
|
-
|
|
35
|
+
const getSharp = loaded?.getSharp;
|
|
36
|
+
if (typeof getSharp === 'function')
|
|
37
|
+
return getSharp;
|
|
38
|
+
throw new Error(`The installed Next.js exposes no getSharp in ${NEXT_SHARP_MODULE}; @brandlab-digital/site-next/image-runtime cannot keep HEIF decoding blocked. Use the Next.js version the Brandlab release pins.`);
|
|
38
39
|
}
|
|
39
40
|
//# sourceMappingURL=next-sharp.js.map
|
package/dist/next-sharp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-sharp.js","sourceRoot":"","sources":["../src/next-sharp.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"next-sharp.js","sourceRoot":"","sources":["../src/next-sharp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,+CAA+C,CAAA;AAEhF;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAA0B,EAC1B,aAA4B;IAE5B,IAAI,CAAC;QACH,WAAW,EAAE,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,kBAAkB;YAAE,OAAO,SAAS,CAAA;QAClF,MAAM,KAAK,CAAA;IACb,CAAC;IACD,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,aAAa,EAAE,CAAA;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACrE,MAAM,IAAI,KAAK,CACb,4DAA4D,iBAAiB,gCAAgC,MAAM,sJAAsJ,EACzQ,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAI,MAAwC,EAAE,QAAQ,CAAA;IACpE,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,QAAyB,CAAA;IACpE,MAAM,IAAI,KAAK,CACb,gDAAgD,iBAAiB,mIAAmI,CACrM,CAAA;AACH,CAAC","sourcesContent":["/**\n * The Next module that holds its private Sharp initialiser on the pinned Next release (16.4 moved `getSharp` from\n * `next/dist/server/image-optimizer.js` to `next/dist/server/image-optimizer/transform.js`). The image runtime calls\n * it before blocking the HEIF decoder, because Next unblocks HEIF the first time its optimiser acquires Sharp.\n *\n * The image runtime must load this module with a literal `require('next/dist/server/image-optimizer/transform.js')`\n * on its own `createRequire(import.meta.url)`. Next's output tracing only copies a module into a deployed route\n * when it sees a literal path there; a path held in a variable or passed through a helper is never traced, so the\n * route fails on Vercel while it passes against a full local `node_modules` (3.12.1–3.15.0).\n */\nexport const NEXT_SHARP_MODULE = 'next/dist/server/image-optimizer/transform.js'\n\n/**\n * The installed Next's `getSharp`, or undefined when Next is not installed. `resolveNext` resolves\n * `next/package.json`; `loadTransform` is the image runtime's literal require of {@link NEXT_SHARP_MODULE}. Throws\n * when Next is installed but the module cannot be loaded (keeping the original error as the cause) or exposes no\n * `getSharp`, so the route fails at startup instead of leaving HEIF decoding open.\n */\nexport function findNextGetSharp(\n resolveNext: () => unknown,\n loadTransform: () => unknown,\n): (() => unknown) | undefined {\n try {\n resolveNext()\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') return undefined\n throw error\n }\n let loaded: unknown\n try {\n loaded = loadTransform()\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error)\n throw new Error(\n `@brandlab-digital/site-next/image-runtime could not load ${NEXT_SHARP_MODULE} from the installed Next.js (${detail}), so it cannot keep HEIF decoding blocked. Use the Next.js version the Brandlab release pins, and check that the deployed route includes that file.`,\n { cause: error },\n )\n }\n const getSharp = (loaded as { getSharp?: unknown } | null)?.getSharp\n if (typeof getSharp === 'function') return getSharp as () => unknown\n throw new Error(\n `The installed Next.js exposes no getSharp in ${NEXT_SHARP_MODULE}; @brandlab-digital/site-next/image-runtime cannot keep HEIF decoding blocked. Use the Next.js version the Brandlab release pins.`,\n )\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":"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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', '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
|
|
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":";
|
|
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"]}
|