@brandlab-digital/site-next 2.0.0 → 3.0.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 (104) hide show
  1. package/dist/analytics.d.ts +111 -52
  2. package/dist/analytics.d.ts.map +1 -1
  3. package/dist/analytics.js +281 -153
  4. package/dist/analytics.js.map +1 -1
  5. package/dist/blog.d.ts +4 -2
  6. package/dist/blog.d.ts.map +1 -1
  7. package/dist/blog.js +7 -7
  8. package/dist/blog.js.map +1 -1
  9. package/dist/contact/client-entry.d.ts +2 -0
  10. package/dist/contact/client-entry.d.ts.map +1 -1
  11. package/dist/contact/client-entry.js +1 -0
  12. package/dist/contact/client-entry.js.map +1 -1
  13. package/dist/contact/client.d.ts +12 -22
  14. package/dist/contact/client.d.ts.map +1 -1
  15. package/dist/contact/client.js +28 -21
  16. package/dist/contact/client.js.map +1 -1
  17. package/dist/contact/form-client.d.ts +148 -0
  18. package/dist/contact/form-client.d.ts.map +1 -0
  19. package/dist/contact/form-client.js +234 -0
  20. package/dist/contact/form-client.js.map +1 -0
  21. package/dist/contact/index.d.ts +1 -1
  22. package/dist/contact/index.d.ts.map +1 -1
  23. package/dist/contact/index.js +1 -1
  24. package/dist/contact/index.js.map +1 -1
  25. package/dist/contact/route-handler.d.ts +32 -0
  26. package/dist/contact/route-handler.d.ts.map +1 -0
  27. package/dist/contact/route-handler.js +44 -0
  28. package/dist/contact/route-handler.js.map +1 -0
  29. package/dist/contact/server-entry.d.ts +1 -0
  30. package/dist/contact/server-entry.d.ts.map +1 -1
  31. package/dist/contact/server-entry.js +1 -0
  32. package/dist/contact/server-entry.js.map +1 -1
  33. package/dist/contact/server.d.ts +5 -0
  34. package/dist/contact/server.d.ts.map +1 -1
  35. package/dist/contact/server.js +13 -7
  36. package/dist/contact/server.js.map +1 -1
  37. package/dist/contact/shared.d.ts +4 -0
  38. package/dist/contact/shared.d.ts.map +1 -1
  39. package/dist/contact/shared.js.map +1 -1
  40. package/dist/contact/testing.d.ts +29 -0
  41. package/dist/contact/testing.d.ts.map +1 -1
  42. package/dist/contact/testing.js +27 -0
  43. package/dist/contact/testing.js.map +1 -1
  44. package/dist/google-reviews-client.d.ts +12 -1
  45. package/dist/google-reviews-client.d.ts.map +1 -1
  46. package/dist/google-reviews-client.js +38 -41
  47. package/dist/google-reviews-client.js.map +1 -1
  48. package/dist/google-reviews-ui.d.ts +4 -2
  49. package/dist/google-reviews-ui.d.ts.map +1 -1
  50. package/dist/google-reviews-ui.js +10 -9
  51. package/dist/google-reviews-ui.js.map +1 -1
  52. package/dist/google-tag-plan.d.ts +1 -4
  53. package/dist/google-tag-plan.d.ts.map +1 -1
  54. package/dist/google-tag-plan.js +1 -14
  55. package/dist/google-tag-plan.js.map +1 -1
  56. package/dist/google-tag.d.ts +5 -4
  57. package/dist/google-tag.d.ts.map +1 -1
  58. package/dist/google-tag.js +5 -4
  59. package/dist/google-tag.js.map +1 -1
  60. package/dist/headers.d.ts +21 -28
  61. package/dist/headers.d.ts.map +1 -1
  62. package/dist/headers.js +62 -51
  63. package/dist/headers.js.map +1 -1
  64. package/dist/instrumentation-client.d.ts +21 -1
  65. package/dist/instrumentation-client.d.ts.map +1 -1
  66. package/dist/instrumentation-client.js +62 -7
  67. package/dist/instrumentation-client.js.map +1 -1
  68. package/dist/lead-registry.d.ts +34 -0
  69. package/dist/lead-registry.d.ts.map +1 -0
  70. package/dist/lead-registry.js +30 -0
  71. package/dist/lead-registry.js.map +1 -0
  72. package/dist/lead-reporting.d.ts +37 -0
  73. package/dist/lead-reporting.d.ts.map +1 -0
  74. package/dist/lead-reporting.js +74 -0
  75. package/dist/lead-reporting.js.map +1 -0
  76. package/dist/metadata.d.ts +10 -11
  77. package/dist/metadata.d.ts.map +1 -1
  78. package/dist/metadata.js +17 -19
  79. package/dist/metadata.js.map +1 -1
  80. package/dist/next-config.d.ts +102 -0
  81. package/dist/next-config.d.ts.map +1 -0
  82. package/dist/next-config.js +140 -0
  83. package/dist/next-config.js.map +1 -0
  84. package/dist/robots.d.ts +14 -6
  85. package/dist/robots.d.ts.map +1 -1
  86. package/dist/robots.js +26 -17
  87. package/dist/robots.js.map +1 -1
  88. package/dist/sitemaps.d.ts +34 -0
  89. package/dist/sitemaps.d.ts.map +1 -1
  90. package/dist/sitemaps.js +66 -1
  91. package/dist/sitemaps.js.map +1 -1
  92. package/dist/testing/server-only.d.ts +8 -0
  93. package/dist/testing/server-only.d.ts.map +1 -0
  94. package/dist/testing/server-only.js +8 -0
  95. package/dist/testing/server-only.js.map +1 -0
  96. package/dist/ui-client.d.ts +1 -12
  97. package/dist/ui-client.d.ts.map +1 -1
  98. package/dist/ui-client.js +0 -17
  99. package/dist/ui-client.js.map +1 -1
  100. package/dist/ui.d.ts +22 -2
  101. package/dist/ui.d.ts.map +1 -1
  102. package/dist/ui.js +67 -6
  103. package/dist/ui.js.map +1 -1
  104. package/package.json +16 -3
@@ -16,13 +16,24 @@ export interface GooglePlaceReviewsClientProps extends Omit<GooglePlaceReviewsPr
16
16
  /** Wrapper used only for lazy activation; projects own its visual treatment. */
17
17
  wrapperProps?: Omit<HTMLAttributes<HTMLDivElement>, 'children'>;
18
18
  }
19
+ /**
20
+ * Inline project-owned presentation sharing its enclosing page provider.
21
+ * Attach ref to the real placement for lazy activation. The caller owns fallback
22
+ * content and must display GooglePlaceReviewsAttribution beside live data.
23
+ */
24
+ export declare function useGooglePlaceReviewsSnapshot<Element extends HTMLElement = HTMLSpanElement>(): {
25
+ ref: import("react").Dispatch<import("react").SetStateAction<Element | null>>;
26
+ snapshot: GooglePlaceReviewsAvailableSnapshot | null;
27
+ };
19
28
  export interface GooglePlaceReviewsProviderProps {
20
29
  endpoint: string;
21
30
  mode: GooglePlaceReviewsMode;
31
+ /** Refreshes only review data on navigation; preserves state in child components. */
32
+ pageKey?: string;
22
33
  children: ReactNode;
23
34
  }
24
35
  /** Shares one in-memory request among matching placements for this page only. */
25
- export declare function GooglePlaceReviewsProvider({ endpoint, mode, children }: GooglePlaceReviewsProviderProps): import("react/jsx-runtime").JSX.Element;
36
+ export declare function GooglePlaceReviewsProvider({ endpoint, mode, pageKey, children }: GooglePlaceReviewsProviderProps): import("react/jsx-runtime").JSX.Element;
26
37
  /**
27
38
  * Cost-aware display controller. It requests live Places data only when the
28
39
  * approved placement approaches the viewport and always retains a stable link.
@@ -1 +1 @@
1
- {"version":3,"file":"google-reviews-client.d.ts","sourceRoot":"","sources":["../src/google-reviews-client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAyF,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAClJ,OAAO,EAIL,KAAK,mCAAmC,EACxC,KAAK,sBAAsB,EAE5B,MAAM,4CAA4C,CAAA;AACnD,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,wBAAwB,CAAA;AAI/B,MAAM,MAAM,gCAAgC,GAAG,WAAW,GAAG,sBAAsB,CAAA;AAEnF,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC;IACjD,IAAI,EAAE,gCAAgC,CAAA;IACtC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iHAAiH;IACjH,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,mCAAmC,KAAK,SAAS,CAAA;IAC7E,gFAAgF;IAChF,YAAY,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,CAAA;CAChE;AA2ED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,sBAAsB,CAAA;IAC5B,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,iFAAiF;AACjF,wBAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,+BAA+B,2CAKvG;AAkBD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,QAAQ,EACR,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,SAAuB,EACvB,GAAG,WAAW,EACf,EAAE,6BAA6B,2CA6F/B"}
1
+ {"version":3,"file":"google-reviews-client.d.ts","sourceRoot":"","sources":["../src/google-reviews-client.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiF,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1I,OAAO,EAIL,KAAK,mCAAmC,EACxC,KAAK,sBAAsB,EAC5B,MAAM,4CAA4C,CAAA;AACnD,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,wBAAwB,CAAA;AAI/B,MAAM,MAAM,gCAAgC,GAAG,WAAW,GAAG,sBAAsB,CAAA;AAEnF,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC;IACjD,IAAI,EAAE,gCAAgC,CAAA;IACtC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,iHAAiH;IACjH,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,uFAAuF;IACvF,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,mCAAmC,KAAK,SAAS,CAAA;IAC7E,gFAAgF;IAChF,YAAY,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC,CAAA;CAChE;AAoGD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,SAAS,WAAW,GAAG,eAAe;;;EAI1F;AAED,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,sBAAsB,CAAA;IAC5B,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,iFAAiF;AACjF,wBAAgB,0BAA0B,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,+BAA+B,2CAKhH;AAkBD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,QAAQ,EACR,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,SAAuB,EACvB,GAAG,WAAW,EACf,EAAE,6BAA6B,2CA6D/B"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
3
+ import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore } from 'react';
4
4
  import { normalizeGooglePlaceReviewsSelection, parseGooglePlaceReviewsSnapshot, selectGooglePlaceReviewsSnapshot, } from '@brandlab-digital/site-core/google-reviews';
5
5
  import { GooglePlaceReviews, GooglePlaceReviewsPolicyAttribution, GoogleReviewsLink, } from './google-reviews-ui.js';
6
6
  const MAXIMUM_ROUTE_RESPONSE_BYTES = 64 * 1_024;
@@ -82,10 +82,42 @@ function createPageReviewStore(endpoint, mode) {
82
82
  const PageReviewsContext = createContext(null);
83
83
  const emptySnapshot = () => null;
84
84
  const emptySubscribe = () => () => { };
85
+ function useReviewSnapshot(store) {
86
+ const [element, ref] = useState(null);
87
+ const snapshot = useSyncExternalStore(store?.subscribe ?? emptySubscribe, store?.getSnapshot ?? emptySnapshot, emptySnapshot);
88
+ useEffect(() => {
89
+ if (!element || !store?.endpoint)
90
+ return;
91
+ if (typeof IntersectionObserver !== 'function') {
92
+ store.activate();
93
+ return;
94
+ }
95
+ const observer = new IntersectionObserver((entries) => {
96
+ if (!entries.some((entry) => entry.isIntersecting))
97
+ return;
98
+ store.activate();
99
+ observer.disconnect();
100
+ }, { rootMargin: '320px 0px' });
101
+ observer.observe(element);
102
+ return () => observer.disconnect();
103
+ }, [element, store]);
104
+ return { ref, snapshot };
105
+ }
106
+ /**
107
+ * Inline project-owned presentation sharing its enclosing page provider.
108
+ * Attach ref to the real placement for lazy activation. The caller owns fallback
109
+ * content and must display GooglePlaceReviewsAttribution beside live data.
110
+ */
111
+ export function useGooglePlaceReviewsSnapshot() {
112
+ const store = useContext(PageReviewsContext);
113
+ if (!store)
114
+ throw new Error('useGooglePlaceReviewsSnapshot requires GooglePlaceReviewsProvider.');
115
+ return useReviewSnapshot(store);
116
+ }
85
117
  /** Shares one in-memory request among matching placements for this page only. */
86
- export function GooglePlaceReviewsProvider({ endpoint, mode, children }) {
118
+ export function GooglePlaceReviewsProvider({ endpoint, mode, pageKey, children }) {
87
119
  const safeEndpoint = normalizeSameOriginEndpoint(endpoint);
88
- const store = useMemo(() => createPageReviewStore(safeEndpoint, mode), [safeEndpoint, mode]);
120
+ const store = useMemo(() => createPageReviewStore(safeEndpoint, mode), [safeEndpoint, mode, pageKey]);
89
121
  useEffect(() => store.mount(), [store]);
90
122
  return _jsx(PageReviewsContext.Provider, { value: store, children: children });
91
123
  }
@@ -97,51 +129,16 @@ function ReviewFallback(props) {
97
129
  * approved placement approaches the viewport and always retains a stable link.
98
130
  */
99
131
  export function GooglePlaceReviewsClient({ mode, endpoint, fallbackGoogleMapsUri, fallbackLabel, fallbackClassName, fallbackContent, renderSnapshot, wrapperProps, selection = 'relevance', ...reviewProps }) {
100
- const wrapperRef = useRef(null);
101
- const [localSnapshot, setSnapshot] = useState(null);
102
- const [activated, setActivated] = useState(false);
103
132
  const safeEndpoint = normalizeSameOriginEndpoint(endpoint);
104
133
  const provider = useContext(PageReviewsContext);
105
134
  const shared = provider?.endpoint === safeEndpoint && provider?.mode === mode ? provider : null;
106
- const sharedSnapshot = useSyncExternalStore(shared?.subscribe ?? emptySubscribe, shared?.getSnapshot ?? emptySnapshot, emptySnapshot);
107
- const snapshot = shared ? sharedSnapshot : localSnapshot;
135
+ const localStore = useMemo(() => !shared && mode !== 'link-only' ? createPageReviewStore(safeEndpoint, mode) : null, [shared, safeEndpoint, mode]);
136
+ useEffect(() => localStore?.mount(), [localStore]);
137
+ const { ref: wrapperRef, snapshot } = useReviewSnapshot(shared ?? localStore);
108
138
  const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection);
109
139
  if (normalizedSelection === 'five-star-featured' && mode !== 'full') {
110
140
  throw new Error('Five-star featured reviews require full mode.');
111
141
  }
112
- useEffect(() => {
113
- if (mode === 'link-only' || !safeEndpoint)
114
- return;
115
- const element = wrapperRef.current;
116
- if (!element)
117
- return;
118
- if (typeof IntersectionObserver !== 'function') {
119
- setActivated(true);
120
- return;
121
- }
122
- const observer = new IntersectionObserver((entries) => {
123
- if (!entries.some((entry) => entry.isIntersecting))
124
- return;
125
- setActivated(true);
126
- observer.disconnect();
127
- }, { rootMargin: '320px 0px' });
128
- observer.observe(element);
129
- return () => observer.disconnect();
130
- }, [mode, safeEndpoint]);
131
- useEffect(() => {
132
- if (!activated || mode === 'link-only' || !safeEndpoint)
133
- return;
134
- if (shared) {
135
- shared.activate();
136
- return;
137
- }
138
- const controller = new AbortController();
139
- void requestSnapshot(safeEndpoint, mode, controller.signal).then((parsed) => {
140
- if (!controller.signal.aborted && parsed)
141
- setSnapshot(parsed);
142
- });
143
- return () => controller.abort();
144
- }, [activated, mode, safeEndpoint, shared]);
145
142
  if (mode === 'link-only') {
146
143
  return (_jsx(ReviewFallback, { fallbackClassName: fallbackClassName, fallbackContent: fallbackContent, fallbackGoogleMapsUri: fallbackGoogleMapsUri, fallbackLabel: fallbackLabel }));
147
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"google-reviews-client.js","sourceRoot":"","sources":["../src/google-reviews-client.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore, type HTMLAttributes, type ReactNode } from 'react'\nimport {\n normalizeGooglePlaceReviewsSelection,\n parseGooglePlaceReviewsSnapshot,\n selectGooglePlaceReviewsSnapshot,\n type GooglePlaceReviewsAvailableSnapshot,\n type GooglePlaceReviewsMode,\n type GooglePlaceReviewsSnapshot,\n} from '@brandlab-digital/site-core/google-reviews'\nimport {\n GooglePlaceReviews,\n GooglePlaceReviewsPolicyAttribution,\n GoogleReviewsLink,\n type GooglePlaceReviewsProps,\n} from './google-reviews-ui.js'\n\nconst MAXIMUM_ROUTE_RESPONSE_BYTES = 64 * 1_024\n\nexport type BrandlabGoogleReviewsDisplayMode = 'link-only' | GooglePlaceReviewsMode\n\nexport interface GooglePlaceReviewsClientProps\n extends Omit<GooglePlaceReviewsProps, 'snapshot'> {\n mode: BrandlabGoogleReviewsDisplayMode\n /** Same-origin Brandlab route. Ignored in link-only mode. */\n endpoint?: string\n fallbackGoogleMapsUri: string\n fallbackLabel?: string\n fallbackClassName?: string\n /** Existing project-owned proof shown while live data is unavailable. The Google link is retained separately. */\n fallbackContent?: ReactNode\n /** Lets the project own all visual presentation while retaining shared data safety. */\n renderSnapshot?: (snapshot: GooglePlaceReviewsAvailableSnapshot) => ReactNode\n /** Wrapper used only for lazy activation; projects own its visual treatment. */\n wrapperProps?: Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n}\n\nfunction normalizeSameOriginEndpoint(value: string | undefined) {\n if (!value || !value.startsWith('/') || value.startsWith('//')) return undefined\n try {\n const parsed = new URL(value, 'https://brandlab.invalid')\n if (parsed.origin !== 'https://brandlab.invalid' || parsed.hash) return undefined\n return `${parsed.pathname}${parsed.search}`\n } catch {\n return undefined\n }\n}\n\nasync function requestSnapshot(endpoint: string, mode: GooglePlaceReviewsMode, signal: AbortSignal) {\n try {\n const response = await fetch(endpoint, {\n cache: 'no-store',\n credentials: 'same-origin',\n headers: { accept: 'application/json' },\n signal,\n })\n if (!response.ok) return null\n const raw = await response.text()\n if (new TextEncoder().encode(raw).byteLength > MAXIMUM_ROUTE_RESPONSE_BYTES) return null\n const parsed = parseGooglePlaceReviewsSnapshot(JSON.parse(raw), mode)\n return parsed?.status === 'available' ? parsed : null\n } catch {\n return null\n }\n}\n\nfunction createPageReviewStore(endpoint: string | undefined, mode: GooglePlaceReviewsMode) {\n let snapshot: GooglePlaceReviewsSnapshot | null = null\n let attempted = false\n let disposed = false\n let lifecycle = 0\n let controller: AbortController | undefined\n const listeners = new Set<() => void>()\n return {\n endpoint,\n mode,\n getSnapshot: () => snapshot,\n subscribe(listener: () => void) {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n },\n activate() {\n if (attempted || disposed || !endpoint) return\n attempted = true\n controller = new AbortController()\n void requestSnapshot(endpoint, mode, controller.signal).then((result) => {\n if (disposed || !result) return\n snapshot = result\n listeners.forEach((listener) => listener())\n })\n },\n mount() {\n const current = ++lifecycle\n return () => {\n // React's development effect replay must not cancel the page's only request.\n queueMicrotask(() => {\n if (lifecycle !== current) return\n disposed = true\n controller?.abort()\n listeners.clear()\n })\n }\n },\n }\n}\n\nconst PageReviewsContext = createContext<ReturnType<typeof createPageReviewStore> | null>(null)\nconst emptySnapshot = () => null\nconst emptySubscribe = () => () => {}\n\nexport interface GooglePlaceReviewsProviderProps {\n endpoint: string\n mode: GooglePlaceReviewsMode\n children: ReactNode\n}\n\n/** Shares one in-memory request among matching placements for this page only. */\nexport function GooglePlaceReviewsProvider({ endpoint, mode, children }: GooglePlaceReviewsProviderProps) {\n const safeEndpoint = normalizeSameOriginEndpoint(endpoint)\n const store = useMemo(() => createPageReviewStore(safeEndpoint, mode), [safeEndpoint, mode])\n useEffect(() => store.mount(), [store])\n return <PageReviewsContext.Provider value={store}>{children}</PageReviewsContext.Provider>\n}\n\nfunction ReviewFallback(props: Pick<\n GooglePlaceReviewsClientProps,\n 'fallbackGoogleMapsUri' | 'fallbackLabel' | 'fallbackClassName' | 'fallbackContent'\n>) {\n return (\n <>\n {props.fallbackContent}\n <GoogleReviewsLink\n className={props.fallbackClassName}\n googleMapsUri={props.fallbackGoogleMapsUri}\n label={props.fallbackLabel}\n />\n </>\n )\n}\n\n/**\n * Cost-aware display controller. It requests live Places data only when the\n * approved placement approaches the viewport and always retains a stable link.\n */\nexport function GooglePlaceReviewsClient({\n mode,\n endpoint,\n fallbackGoogleMapsUri,\n fallbackLabel,\n fallbackClassName,\n fallbackContent,\n renderSnapshot,\n wrapperProps,\n selection = 'relevance',\n ...reviewProps\n}: GooglePlaceReviewsClientProps) {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const [localSnapshot, setSnapshot] = useState<GooglePlaceReviewsSnapshot | null>(null)\n const [activated, setActivated] = useState(false)\n const safeEndpoint = normalizeSameOriginEndpoint(endpoint)\n const provider = useContext(PageReviewsContext)\n const shared = provider?.endpoint === safeEndpoint && provider?.mode === mode ? provider : null\n const sharedSnapshot = useSyncExternalStore(shared?.subscribe ?? emptySubscribe, shared?.getSnapshot ?? emptySnapshot, emptySnapshot)\n const snapshot = shared ? sharedSnapshot : localSnapshot\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n if (normalizedSelection === 'five-star-featured' && mode !== 'full') {\n throw new Error('Five-star featured reviews require full mode.')\n }\n\n useEffect(() => {\n if (mode === 'link-only' || !safeEndpoint) return\n const element = wrapperRef.current\n if (!element) return\n if (typeof IntersectionObserver !== 'function') {\n setActivated(true)\n return\n }\n const observer = new IntersectionObserver(\n (entries) => {\n if (!entries.some((entry) => entry.isIntersecting)) return\n setActivated(true)\n observer.disconnect()\n },\n { rootMargin: '320px 0px' },\n )\n observer.observe(element)\n return () => observer.disconnect()\n }, [mode, safeEndpoint])\n\n useEffect(() => {\n if (!activated || mode === 'link-only' || !safeEndpoint) return\n if (shared) {\n shared.activate()\n return\n }\n const controller = new AbortController()\n void requestSnapshot(safeEndpoint, mode, controller.signal).then((parsed) => {\n if (!controller.signal.aborted && parsed) setSnapshot(parsed)\n })\n return () => controller.abort()\n }, [activated, mode, safeEndpoint, shared])\n\n if (mode === 'link-only') {\n return (\n <ReviewFallback\n fallbackClassName={fallbackClassName}\n fallbackContent={fallbackContent}\n fallbackGoogleMapsUri={fallbackGoogleMapsUri}\n fallbackLabel={fallbackLabel}\n />\n )\n }\n\n return (\n <div {...wrapperProps} ref={wrapperRef}>\n {snapshot?.status === 'available'\n ? renderSnapshot\n ? (\n <>\n {renderSnapshot(selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection))}\n <GooglePlaceReviewsPolicyAttribution\n attributionMode={reviewProps.attributionMode}\n attributionTone={reviewProps.attributionTone}\n className={reviewProps.attributionClassName}\n policyAttributionClassName={reviewProps.policyAttributionClassName}\n policyClassName={reviewProps.policyClassName}\n selection={normalizedSelection}\n snapshot={selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection)}\n />\n </>\n )\n : (\n <GooglePlaceReviews\n {...reviewProps}\n selection={normalizedSelection}\n snapshot={snapshot}\n />\n )\n : (\n <ReviewFallback\n fallbackClassName={fallbackClassName}\n fallbackContent={fallbackContent}\n fallbackGoogleMapsUri={fallbackGoogleMapsUri}\n fallbackLabel={fallbackLabel}\n />\n )}\n </div>\n )\n}\n"]}
1
+ {"version":3,"file":"google-reviews-client.js","sourceRoot":"","sources":["../src/google-reviews-client.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client'\n\nimport { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, type HTMLAttributes, type ReactNode } from 'react'\nimport {\n normalizeGooglePlaceReviewsSelection,\n parseGooglePlaceReviewsSnapshot,\n selectGooglePlaceReviewsSnapshot,\n type GooglePlaceReviewsAvailableSnapshot,\n type GooglePlaceReviewsMode,\n} from '@brandlab-digital/site-core/google-reviews'\nimport {\n GooglePlaceReviews,\n GooglePlaceReviewsPolicyAttribution,\n GoogleReviewsLink,\n type GooglePlaceReviewsProps,\n} from './google-reviews-ui.js'\n\nconst MAXIMUM_ROUTE_RESPONSE_BYTES = 64 * 1_024\n\nexport type BrandlabGoogleReviewsDisplayMode = 'link-only' | GooglePlaceReviewsMode\n\nexport interface GooglePlaceReviewsClientProps\n extends Omit<GooglePlaceReviewsProps, 'snapshot'> {\n mode: BrandlabGoogleReviewsDisplayMode\n /** Same-origin Brandlab route. Ignored in link-only mode. */\n endpoint?: string\n fallbackGoogleMapsUri: string\n fallbackLabel?: string\n fallbackClassName?: string\n /** Existing project-owned proof shown while live data is unavailable. The Google link is retained separately. */\n fallbackContent?: ReactNode\n /** Lets the project own all visual presentation while retaining shared data safety. */\n renderSnapshot?: (snapshot: GooglePlaceReviewsAvailableSnapshot) => ReactNode\n /** Wrapper used only for lazy activation; projects own its visual treatment. */\n wrapperProps?: Omit<HTMLAttributes<HTMLDivElement>, 'children'>\n}\n\nfunction normalizeSameOriginEndpoint(value: string | undefined) {\n if (!value || !value.startsWith('/') || value.startsWith('//')) return undefined\n try {\n const parsed = new URL(value, 'https://brandlab.invalid')\n if (parsed.origin !== 'https://brandlab.invalid' || parsed.hash) return undefined\n return `${parsed.pathname}${parsed.search}`\n } catch {\n return undefined\n }\n}\n\nasync function requestSnapshot(endpoint: string, mode: GooglePlaceReviewsMode, signal: AbortSignal) {\n try {\n const response = await fetch(endpoint, {\n cache: 'no-store',\n credentials: 'same-origin',\n headers: { accept: 'application/json' },\n signal,\n })\n if (!response.ok) return null\n const raw = await response.text()\n if (new TextEncoder().encode(raw).byteLength > MAXIMUM_ROUTE_RESPONSE_BYTES) return null\n const parsed = parseGooglePlaceReviewsSnapshot(JSON.parse(raw), mode)\n return parsed?.status === 'available' ? parsed : null\n } catch {\n return null\n }\n}\n\nfunction createPageReviewStore(endpoint: string | undefined, mode: GooglePlaceReviewsMode) {\n let snapshot: GooglePlaceReviewsAvailableSnapshot | null = null\n let attempted = false\n let disposed = false\n let lifecycle = 0\n let controller: AbortController | undefined\n const listeners = new Set<() => void>()\n return {\n endpoint,\n mode,\n getSnapshot: () => snapshot,\n subscribe(listener: () => void) {\n listeners.add(listener)\n return () => { listeners.delete(listener) }\n },\n activate() {\n if (attempted || disposed || !endpoint) return\n attempted = true\n controller = new AbortController()\n void requestSnapshot(endpoint, mode, controller.signal).then((result) => {\n if (disposed || !result) return\n snapshot = result\n listeners.forEach((listener) => listener())\n })\n },\n mount() {\n const current = ++lifecycle\n return () => {\n // React's development effect replay must not cancel the page's only request.\n queueMicrotask(() => {\n if (lifecycle !== current) return\n disposed = true\n controller?.abort()\n listeners.clear()\n })\n }\n },\n }\n}\n\nconst PageReviewsContext = createContext<ReturnType<typeof createPageReviewStore> | null>(null)\nconst emptySnapshot = () => null\nconst emptySubscribe = () => () => {}\n\nfunction useReviewSnapshot<Element extends HTMLElement>(store: ReturnType<typeof createPageReviewStore> | null) {\n const [element, ref] = useState<Element | null>(null)\n const snapshot = useSyncExternalStore(store?.subscribe ?? emptySubscribe, store?.getSnapshot ?? emptySnapshot, emptySnapshot)\n\n useEffect(() => {\n if (!element || !store?.endpoint) return\n if (typeof IntersectionObserver !== 'function') {\n store.activate()\n return\n }\n const observer = new IntersectionObserver(\n (entries) => {\n if (!entries.some((entry) => entry.isIntersecting)) return\n store.activate()\n observer.disconnect()\n },\n { rootMargin: '320px 0px' },\n )\n observer.observe(element)\n return () => observer.disconnect()\n }, [element, store])\n\n return { ref, snapshot }\n}\n\n/**\n * Inline project-owned presentation sharing its enclosing page provider.\n * Attach ref to the real placement for lazy activation. The caller owns fallback\n * content and must display GooglePlaceReviewsAttribution beside live data.\n */\nexport function useGooglePlaceReviewsSnapshot<Element extends HTMLElement = HTMLSpanElement>() {\n const store = useContext(PageReviewsContext)\n if (!store) throw new Error('useGooglePlaceReviewsSnapshot requires GooglePlaceReviewsProvider.')\n return useReviewSnapshot<Element>(store)\n}\n\nexport interface GooglePlaceReviewsProviderProps {\n endpoint: string\n mode: GooglePlaceReviewsMode\n /** Refreshes only review data on navigation; preserves state in child components. */\n pageKey?: string\n children: ReactNode\n}\n\n/** Shares one in-memory request among matching placements for this page only. */\nexport function GooglePlaceReviewsProvider({ endpoint, mode, pageKey, children }: GooglePlaceReviewsProviderProps) {\n const safeEndpoint = normalizeSameOriginEndpoint(endpoint)\n const store = useMemo(() => createPageReviewStore(safeEndpoint, mode), [safeEndpoint, mode, pageKey])\n useEffect(() => store.mount(), [store])\n return <PageReviewsContext.Provider value={store}>{children}</PageReviewsContext.Provider>\n}\n\nfunction ReviewFallback(props: Pick<\n GooglePlaceReviewsClientProps,\n 'fallbackGoogleMapsUri' | 'fallbackLabel' | 'fallbackClassName' | 'fallbackContent'\n>) {\n return (\n <>\n {props.fallbackContent}\n <GoogleReviewsLink\n className={props.fallbackClassName}\n googleMapsUri={props.fallbackGoogleMapsUri}\n label={props.fallbackLabel}\n />\n </>\n )\n}\n\n/**\n * Cost-aware display controller. It requests live Places data only when the\n * approved placement approaches the viewport and always retains a stable link.\n */\nexport function GooglePlaceReviewsClient({\n mode,\n endpoint,\n fallbackGoogleMapsUri,\n fallbackLabel,\n fallbackClassName,\n fallbackContent,\n renderSnapshot,\n wrapperProps,\n selection = 'relevance',\n ...reviewProps\n}: GooglePlaceReviewsClientProps) {\n const safeEndpoint = normalizeSameOriginEndpoint(endpoint)\n const provider = useContext(PageReviewsContext)\n const shared = provider?.endpoint === safeEndpoint && provider?.mode === mode ? provider : null\n const localStore = useMemo(\n () => !shared && mode !== 'link-only' ? createPageReviewStore(safeEndpoint, mode) : null,\n [shared, safeEndpoint, mode],\n )\n useEffect(() => localStore?.mount(), [localStore])\n const { ref: wrapperRef, snapshot } = useReviewSnapshot<HTMLDivElement>(shared ?? localStore)\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n if (normalizedSelection === 'five-star-featured' && mode !== 'full') {\n throw new Error('Five-star featured reviews require full mode.')\n }\n\n if (mode === 'link-only') {\n return (\n <ReviewFallback\n fallbackClassName={fallbackClassName}\n fallbackContent={fallbackContent}\n fallbackGoogleMapsUri={fallbackGoogleMapsUri}\n fallbackLabel={fallbackLabel}\n />\n )\n }\n\n return (\n <div {...wrapperProps} ref={wrapperRef}>\n {snapshot?.status === 'available'\n ? renderSnapshot\n ? (\n <>\n {renderSnapshot(selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection))}\n <GooglePlaceReviewsPolicyAttribution\n attributionMode={reviewProps.attributionMode}\n attributionTone={reviewProps.attributionTone}\n className={reviewProps.attributionClassName}\n policyAttributionClassName={reviewProps.policyAttributionClassName}\n policyClassName={reviewProps.policyClassName}\n selection={normalizedSelection}\n snapshot={selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection)}\n />\n </>\n )\n : (\n <GooglePlaceReviews\n {...reviewProps}\n selection={normalizedSelection}\n snapshot={snapshot}\n />\n )\n : (\n <ReviewFallback\n fallbackClassName={fallbackClassName}\n fallbackContent={fallbackContent}\n fallbackGoogleMapsUri={fallbackGoogleMapsUri}\n fallbackLabel={fallbackLabel}\n />\n )}\n </div>\n )\n}\n"]}
@@ -319,6 +319,8 @@ export interface GooglePlaceReviewsProps extends HTMLAttributes<HTMLElement> {
319
319
  export interface GooglePlaceReviewsAttributionProps {
320
320
  snapshot: GooglePlaceReviewsAvailableSnapshot;
321
321
  className?: string;
322
+ /** Uses phrasing elements for placement beside inline data. Keep outside links. */
323
+ inline?: boolean;
322
324
  attributionTone?: NonNullable<GooglePlaceReviewsProps['attributionTone']>;
323
325
  attributionMode?: NonNullable<GooglePlaceReviewsProps['attributionMode']>;
324
326
  }
@@ -347,11 +349,11 @@ export declare function GooglePlaceReviewActions({ review, className, }: GoogleP
347
349
  'data-brandlab-google-review-actions': string;
348
350
  }, HTMLElement> | null;
349
351
  /** Required provider attribution with no project styling or layout policy. */
350
- export declare function GooglePlaceReviewsAttribution({ snapshot, className, attributionTone, attributionMode, }: GooglePlaceReviewsAttributionProps): import("react").DetailedReactHTMLElement<{
352
+ export declare function GooglePlaceReviewsAttribution({ snapshot, className, inline, attributionTone, attributionMode, }: GooglePlaceReviewsAttributionProps): import("react").DetailedReactHTMLElement<{
351
353
  className: string | undefined;
352
354
  'data-brandlab-google-reviews-attribution': string;
353
355
  }, HTMLElement>;
354
- export declare function GooglePlaceReviewsPolicyAttribution({ snapshot, selection, className, policyClassName, policyAttributionClassName, attributionTone, attributionMode, }: GooglePlaceReviewsPolicyAttributionProps): import("react").DetailedReactHTMLElement<{
356
+ export declare function GooglePlaceReviewsPolicyAttribution({ snapshot, selection, className, policyClassName, policyAttributionClassName, inline, attributionTone, attributionMode, }: GooglePlaceReviewsPolicyAttributionProps): import("react").DetailedReactHTMLElement<{
355
357
  className: string | undefined;
356
358
  'data-brandlab-google-review-selection': GooglePlaceReviewsSelection;
357
359
  'data-brandlab-google-reviews-policy-attribution': string;
@@ -1 +1 @@
1
- {"version":3,"file":"google-reviews-ui.d.ts","sourceRoot":"","sources":["../src/google-reviews-ui.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"google-reviews-ui.d.ts","sourceRoot":"","sources":["../src/google-reviews-ui.ts"],"names":[],"mappings":"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"}
@@ -156,35 +156,36 @@ function renderReview(review, index, props) {
156
156
  })), createElement('blockquote', { className: props.textClassName }, createElement('p', null, review.text)));
157
157
  }
158
158
  /** Required provider attribution with no project styling or layout policy. */
159
- export function GooglePlaceReviewsAttribution({ snapshot, className, attributionTone = 'light', attributionMode = 'logo', }) {
159
+ export function GooglePlaceReviewsAttribution({ snapshot, className, inline = false, attributionTone = 'light', attributionMode = 'logo', }) {
160
160
  const attributionUrl = normalizeGooglePlacePublicUrl(snapshot.googleMapsUri);
161
- return createElement('div', {
161
+ return createElement(inline ? 'span' : 'div', {
162
162
  className,
163
163
  'data-brandlab-google-reviews-attribution': 'required',
164
164
  }, ...snapshot.thirdPartyAttributions.map((item) => {
165
165
  const providerUri = normalizeGooglePlacePublicUrl(item.providerUri);
166
- return createElement('p', { key: `${item.provider}:${providerUri ?? ''}` }, 'Data provider: ', providerUri
166
+ return createElement(inline ? 'span' : 'p', { key: `${item.provider}:${providerUri ?? ''}` }, 'Data provider: ', providerUri
167
167
  ? createElement('a', externalLinkProps(providerUri), item.provider)
168
- : item.provider);
169
- }), createElement('p', null, 'Reviews provided by ', renderGoogleMapsAttribution(attributionUrl, attributionMode, attributionTone)));
168
+ : item.provider, inline ? ' ' : null);
169
+ }), createElement(inline ? 'span' : 'p', null, 'Reviews provided by ', renderGoogleMapsAttribution(attributionUrl, attributionMode, attributionTone)));
170
170
  }
171
- export function GooglePlaceReviewsPolicyAttribution({ snapshot, selection = 'relevance', className, policyClassName, policyAttributionClassName, attributionTone = 'light', attributionMode = 'logo', }) {
171
+ export function GooglePlaceReviewsPolicyAttribution({ snapshot, selection = 'relevance', className, policyClassName, policyAttributionClassName, inline = false, attributionTone = 'light', attributionMode = 'logo', }) {
172
172
  const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection);
173
173
  const policy = snapshot.mode === 'full' && snapshot.reviews.length > 0
174
174
  ? normalizedSelection === 'five-star-featured'
175
175
  ? "Showing 5-star reviews selected from Google's relevance-ranked results."
176
176
  : 'Google Maps reviews are ordered by relevance.'
177
177
  : null;
178
- return createElement('div', {
178
+ return createElement(inline ? 'span' : 'div', {
179
179
  className: policyAttributionClassName,
180
180
  'data-brandlab-google-review-selection': normalizedSelection,
181
181
  'data-brandlab-google-reviews-policy-attribution': 'compact',
182
182
  }, policy
183
- ? createElement('p', {
183
+ ? createElement(inline ? 'span' : 'p', {
184
184
  className: policyClassName,
185
185
  'data-brandlab-google-review-ordering': normalizedSelection,
186
- }, policy)
186
+ }, inline ? `${policy} ` : policy)
187
187
  : null, createElement(GooglePlaceReviewsAttribution, {
188
+ inline,
188
189
  attributionMode,
189
190
  attributionTone,
190
191
  className,
@@ -1 +1 @@
1
- {"version":3,"file":"google-reviews-ui.js","sourceRoot":"","sources":["../src/google-reviews-ui.ts"],"names":[],"mappings":"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","sourcesContent":["import { createElement, type AnchorHTMLAttributes, type HTMLAttributes } from 'react'\nimport {\n GOOGLE_MAPS_ATTRIBUTION_LABEL,\n GOOGLE_MAPS_ATTRIBUTION_TEXT,\n GOOGLE_PLACE_REVIEWS_MAX_REVIEWS,\n normalizeGooglePlacePublicUrl,\n normalizeGooglePlaceReviewsSelection,\n selectGooglePlaceReviewsSnapshot,\n type GooglePlaceReview,\n type GooglePlaceReviewsAvailableSnapshot,\n type GooglePlaceReviewsSelection,\n type GooglePlaceReviewsSnapshot,\n} from '@brandlab-digital/site-core/google-reviews'\nimport {\n GOOGLE_MAPS_ATTRIBUTION_LOGO_DATA_URL,\n GOOGLE_MAPS_ATTRIBUTION_LOGO_HEIGHT,\n GOOGLE_MAPS_ATTRIBUTION_LOGO_WIDTH,\n} from './google-maps-attribution-assets.js'\n\nexport interface GoogleReviewsLinkProps\n extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\n googleMapsUri: string\n label?: string\n}\n\nexport function GoogleReviewsLink({\n googleMapsUri,\n label = 'Read our Google reviews',\n ...anchorProps\n}: GoogleReviewsLinkProps) {\n const href = normalizeGooglePlacePublicUrl(googleMapsUri)\n if (!href) return null\n return createElement(\n 'a',\n {\n ...anchorProps,\n href,\n 'data-brandlab-google-reviews': 'link-only',\n referrerPolicy: 'no-referrer',\n rel: 'noopener noreferrer',\n target: '_blank',\n },\n label,\n )\n}\n\nexport interface GooglePlaceReviewsProps extends HTMLAttributes<HTMLElement> {\n snapshot: GooglePlaceReviewsSnapshot\n reviewClassName?: string\n authorClassName?: string\n avatarClassName?: string\n actionsClassName?: string\n textClassName?: string\n attributionClassName?: string\n /** Styles the required review-ordering notice in full mode. */\n policyClassName?: string\n /** Styles the compact policy and provider-attribution row. */\n policyAttributionClassName?: string\n allReviewsLinkClassName?: string\n allReviewsLinkLabel?: string\n /** Keeps source order or presents up to three five-star reviews from the relevance window. */\n selection?: GooglePlaceReviewsSelection\n /** Selects the approved Google Maps attribution asset for the project background. */\n attributionTone?: 'light' | 'dark'\n /** Text is reserved for interfaces that cannot accommodate the official logo. */\n attributionMode?: 'logo' | 'text-constrained-space'\n}\n\nexport interface GooglePlaceReviewsAttributionProps {\n snapshot: GooglePlaceReviewsAvailableSnapshot\n className?: string\n attributionTone?: NonNullable<GooglePlaceReviewsProps['attributionTone']>\n attributionMode?: NonNullable<GooglePlaceReviewsProps['attributionMode']>\n}\n\nexport interface GooglePlaceReviewAuthorProps {\n review: GooglePlaceReview\n className?: string\n avatarClassName?: string\n}\n\nexport interface GooglePlaceReviewActionsProps {\n review: GooglePlaceReview\n className?: string\n}\n\nexport interface GooglePlaceReviewsPolicyAttributionProps\n extends GooglePlaceReviewsAttributionProps {\n selection?: GooglePlaceReviewsSelection\n policyClassName?: string\n policyAttributionClassName?: string\n}\n\nfunction assertNonEmptyText(value: unknown, field: string) {\n if (typeof value !== 'string' || !value.trim()) {\n throw new Error(`${field} is required for Google Places rendering.`)\n }\n}\n\nfunction assertPublicUrl(value: unknown, field: string, required = false) {\n if (value === undefined && !required) return\n if (typeof value !== 'string' || !normalizeGooglePlacePublicUrl(value)) {\n throw new Error(`${field} must be a credential-free HTTPS URL.`)\n }\n}\n\nfunction assertGooglePlaceReviewsSnapshotIsRenderable(\n snapshot: GooglePlaceReviewsAvailableSnapshot,\n) {\n assertNonEmptyText(snapshot.businessName, 'snapshot.businessName')\n assertPublicUrl(snapshot.googleMapsUri, 'snapshot.googleMapsUri', true)\n if (!['summary', 'full'].includes(snapshot.mode)) {\n throw new Error('snapshot.mode must be summary or full.')\n }\n if (\n snapshot.attribution?.label !== GOOGLE_MAPS_ATTRIBUTION_LABEL ||\n snapshot.attribution?.text !== GOOGLE_MAPS_ATTRIBUTION_TEXT\n ) {\n throw new Error('Google Maps attribution must use the unmodified shared label and text.')\n }\n if (\n !Array.isArray(snapshot.reviews) ||\n snapshot.reviews.length > GOOGLE_PLACE_REVIEWS_MAX_REVIEWS ||\n (snapshot.mode === 'summary' && snapshot.reviews.length > 0)\n ) {\n throw new Error('Google Places review content does not match the declared display mode.')\n }\n if (!Array.isArray(snapshot.thirdPartyAttributions)) {\n throw new Error('snapshot.thirdPartyAttributions is required for provider attribution.')\n }\n\n snapshot.reviews.forEach((review, index) => {\n assertNonEmptyText(review.authorName, `snapshot.reviews[${index}].authorName`)\n assertNonEmptyText(review.text, `snapshot.reviews[${index}].text`)\n assertPublicUrl(review.googleMapsUri, `snapshot.reviews[${index}].googleMapsUri`, true)\n assertPublicUrl(review.authorUri, `snapshot.reviews[${index}].authorUri`)\n assertPublicUrl(review.authorPhotoUri, `snapshot.reviews[${index}].authorPhotoUri`)\n assertPublicUrl(review.flagContentUri, `snapshot.reviews[${index}].flagContentUri`)\n })\n snapshot.thirdPartyAttributions.forEach((item, index) => {\n assertNonEmptyText(item.provider, `snapshot.thirdPartyAttributions[${index}].provider`)\n assertPublicUrl(item.providerUri, `snapshot.thirdPartyAttributions[${index}].providerUri`)\n })\n}\n\nfunction externalLinkProps(href: string) {\n return {\n href,\n referrerPolicy: 'no-referrer' as const,\n rel: 'noopener noreferrer',\n target: '_blank' as const,\n }\n}\n\n/** Reviewer identity. The avatar identifies and links to the author; it is not an actions button. */\nexport function GooglePlaceReviewAuthor({\n review,\n className,\n avatarClassName,\n}: GooglePlaceReviewAuthorProps) {\n const authorUri = normalizeGooglePlacePublicUrl(review.authorUri)\n const authorPhotoUri = normalizeGooglePlacePublicUrl(review.authorPhotoUri)\n const children = [\n authorPhotoUri\n ? createElement('img', {\n alt: '',\n className: avatarClassName,\n decoding: 'async',\n 'data-brandlab-google-review-avatar': 'author',\n height: 40,\n key: 'avatar',\n loading: 'lazy',\n referrerPolicy: 'no-referrer',\n src: authorPhotoUri,\n width: 40,\n })\n : null,\n createElement('span', { key: 'name' }, review.authorName),\n ]\n\n return authorUri\n ? createElement(\n 'a',\n {\n ...externalLinkProps(authorUri),\n className,\n 'data-brandlab-google-review-author': 'profile-link',\n },\n ...children,\n )\n : createElement(\n 'span',\n {\n className,\n 'data-brandlab-google-review-author': 'text',\n },\n ...children,\n )\n}\n\n/** Compact per-review source and reporting actions with no client JavaScript. */\nexport function GooglePlaceReviewActions({\n review,\n className,\n}: GooglePlaceReviewActionsProps) {\n const sourceUrl = normalizeGooglePlacePublicUrl(review.googleMapsUri)\n const flagContentUri = normalizeGooglePlacePublicUrl(review.flagContentUri)\n if (!sourceUrl) return null\n\n return createElement(\n 'details',\n {\n className,\n 'data-brandlab-google-review-actions': 'details',\n },\n createElement(\n 'summary',\n {\n 'aria-label': `Review options for ${review.authorName}`,\n 'data-brandlab-google-review-actions': 'trigger',\n },\n createElement('span', { 'aria-hidden': true }, '•••'),\n ),\n createElement(\n 'div',\n { 'data-brandlab-google-review-actions': 'menu' },\n createElement(\n 'a',\n {\n ...externalLinkProps(sourceUrl),\n 'data-brandlab-google-review-action': 'source',\n },\n 'Read this review on Google Maps',\n ),\n flagContentUri\n ? createElement(\n 'a',\n {\n ...externalLinkProps(flagContentUri),\n 'data-brandlab-google-review-action': 'report',\n },\n 'Report this review to Google',\n )\n : null,\n ),\n )\n}\n\nfunction renderGoogleMapsAttribution(\n attributionUrl: string | undefined,\n mode: NonNullable<GooglePlaceReviewsProps['attributionMode']>,\n tone: NonNullable<GooglePlaceReviewsProps['attributionTone']>,\n) {\n const content = mode === 'logo'\n ? createElement('img', {\n alt: GOOGLE_MAPS_ATTRIBUTION_LABEL,\n decoding: 'async',\n draggable: false,\n height: GOOGLE_MAPS_ATTRIBUTION_LOGO_HEIGHT,\n src: GOOGLE_MAPS_ATTRIBUTION_LOGO_DATA_URL[tone],\n width: GOOGLE_MAPS_ATTRIBUTION_LOGO_WIDTH,\n })\n : createElement(\n 'span',\n {\n 'data-brandlab-google-maps-attribution': 'text-constrained-space',\n translate: 'no' as const,\n },\n GOOGLE_MAPS_ATTRIBUTION_TEXT,\n )\n\n if (!attributionUrl) return content\n return createElement(\n 'a',\n {\n ...externalLinkProps(attributionUrl),\n 'aria-label': GOOGLE_MAPS_ATTRIBUTION_LABEL,\n 'data-brandlab-google-maps-attribution': mode,\n },\n content,\n )\n}\n\nfunction renderReview(\n review: GooglePlaceReview,\n index: number,\n props: GooglePlaceReviewsProps,\n) {\n return createElement(\n 'article',\n { className: props.reviewClassName, key: `${review.authorName}:${review.publishTime ?? index}` },\n createElement(\n 'header',\n null,\n createElement(GooglePlaceReviewAuthor, {\n avatarClassName: props.avatarClassName,\n className: props.authorClassName,\n review,\n }),\n review.rating\n ? createElement(\n 'span',\n { 'aria-label': `${review.rating} out of 5 stars` },\n `${review.rating}/5`,\n )\n : null,\n review.relativePublishTimeDescription\n ? createElement(\n 'time',\n { dateTime: review.publishTime },\n review.relativePublishTimeDescription,\n )\n : null,\n createElement(GooglePlaceReviewActions, {\n className: props.actionsClassName,\n review,\n }),\n ),\n createElement('blockquote', { className: props.textClassName }, createElement('p', null, review.text)),\n )\n}\n\n/** Required provider attribution with no project styling or layout policy. */\nexport function GooglePlaceReviewsAttribution({\n snapshot,\n className,\n attributionTone = 'light',\n attributionMode = 'logo',\n}: GooglePlaceReviewsAttributionProps) {\n const attributionUrl = normalizeGooglePlacePublicUrl(snapshot.googleMapsUri)\n return createElement(\n 'div',\n {\n className,\n 'data-brandlab-google-reviews-attribution': 'required',\n },\n ...snapshot.thirdPartyAttributions.map((item) => {\n const providerUri = normalizeGooglePlacePublicUrl(item.providerUri)\n return createElement(\n 'p',\n { key: `${item.provider}:${providerUri ?? ''}` },\n 'Data provider: ',\n providerUri\n ? createElement('a', externalLinkProps(providerUri), item.provider)\n : item.provider,\n )\n }),\n createElement(\n 'p',\n null,\n 'Reviews provided by ',\n renderGoogleMapsAttribution(attributionUrl, attributionMode, attributionTone),\n ),\n )\n}\n\nexport function GooglePlaceReviewsPolicyAttribution({\n snapshot,\n selection = 'relevance',\n className,\n policyClassName,\n policyAttributionClassName,\n attributionTone = 'light',\n attributionMode = 'logo',\n}: GooglePlaceReviewsPolicyAttributionProps) {\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n const policy = snapshot.mode === 'full' && snapshot.reviews.length > 0\n ? normalizedSelection === 'five-star-featured'\n ? \"Showing 5-star reviews selected from Google's relevance-ranked results.\"\n : 'Google Maps reviews are ordered by relevance.'\n : null\n\n return createElement(\n 'div',\n {\n className: policyAttributionClassName,\n 'data-brandlab-google-review-selection': normalizedSelection,\n 'data-brandlab-google-reviews-policy-attribution': 'compact',\n },\n policy\n ? createElement(\n 'p',\n {\n className: policyClassName,\n 'data-brandlab-google-review-ordering': normalizedSelection,\n },\n policy,\n )\n : null,\n createElement(GooglePlaceReviewsAttribution, {\n attributionMode,\n attributionTone,\n className,\n snapshot,\n }),\n )\n}\n\n/**\n * Minimal, unstyled Places output. Projects may use this semantic renderer or\n * render a validated snapshot themselves through GooglePlaceReviewsClient.\n */\nexport function GooglePlaceReviews({\n snapshot,\n reviewClassName,\n authorClassName,\n avatarClassName,\n actionsClassName,\n textClassName,\n attributionClassName,\n policyClassName,\n policyAttributionClassName,\n allReviewsLinkClassName,\n allReviewsLinkLabel = 'Read all reviews on Google Maps',\n selection = 'relevance',\n attributionTone = 'light',\n attributionMode = 'logo',\n ...sectionProps\n}: GooglePlaceReviewsProps) {\n if (snapshot.status !== 'available') return null\n assertGooglePlaceReviewsSnapshotIsRenderable(snapshot)\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n if (normalizedSelection === 'five-star-featured' && snapshot.mode !== 'full') {\n throw new Error('Five-star featured reviews require full mode.')\n }\n const displayedSnapshot = selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection)\n const props = {\n ...sectionProps,\n snapshot: displayedSnapshot,\n reviewClassName,\n authorClassName,\n avatarClassName,\n actionsClassName,\n textClassName,\n attributionClassName,\n attributionTone,\n attributionMode,\n }\n return createElement(\n 'section',\n {\n ...sectionProps,\n 'aria-label': sectionProps['aria-label'] ?? `${snapshot.businessName} reviews on Google Maps`,\n 'data-brandlab-google-reviews': `attribution-complete-${snapshot.mode}`,\n 'data-brandlab-google-attribution-mode': attributionMode,\n 'data-brandlab-google-review-count': displayedSnapshot.reviews.length,\n 'data-brandlab-google-review-selection': normalizedSelection,\n },\n snapshot.rating\n ? createElement(\n 'p',\n {\n 'aria-label': `Average rating ${snapshot.rating} out of 5${\n snapshot.userRatingCount === undefined ? '' : ` from ${snapshot.userRatingCount} reviews`\n }`,\n },\n `${snapshot.rating}/5${\n snapshot.userRatingCount === undefined ? '' : ` from ${snapshot.userRatingCount} reviews`\n }`,\n )\n : null,\n ...displayedSnapshot.reviews.map((review, index) => renderReview(review, index, props)),\n normalizedSelection === 'five-star-featured' && displayedSnapshot.reviews.length === 0\n ? createElement(GoogleReviewsLink, {\n className: allReviewsLinkClassName,\n googleMapsUri: displayedSnapshot.googleMapsUri,\n label: allReviewsLinkLabel,\n })\n : null,\n createElement(GooglePlaceReviewsPolicyAttribution, {\n attributionMode,\n attributionTone,\n className: attributionClassName,\n policyAttributionClassName,\n policyClassName,\n selection: normalizedSelection,\n snapshot: displayedSnapshot,\n }),\n )\n}\n"]}
1
+ {"version":3,"file":"google-reviews-ui.js","sourceRoot":"","sources":["../src/google-reviews-ui.ts"],"names":[],"mappings":"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","sourcesContent":["import { createElement, type AnchorHTMLAttributes, type HTMLAttributes } from 'react'\nimport {\n GOOGLE_MAPS_ATTRIBUTION_LABEL,\n GOOGLE_MAPS_ATTRIBUTION_TEXT,\n GOOGLE_PLACE_REVIEWS_MAX_REVIEWS,\n normalizeGooglePlacePublicUrl,\n normalizeGooglePlaceReviewsSelection,\n selectGooglePlaceReviewsSnapshot,\n type GooglePlaceReview,\n type GooglePlaceReviewsAvailableSnapshot,\n type GooglePlaceReviewsSelection,\n type GooglePlaceReviewsSnapshot,\n} from '@brandlab-digital/site-core/google-reviews'\nimport {\n GOOGLE_MAPS_ATTRIBUTION_LOGO_DATA_URL,\n GOOGLE_MAPS_ATTRIBUTION_LOGO_HEIGHT,\n GOOGLE_MAPS_ATTRIBUTION_LOGO_WIDTH,\n} from './google-maps-attribution-assets.js'\n\nexport interface GoogleReviewsLinkProps\n extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {\n googleMapsUri: string\n label?: string\n}\n\nexport function GoogleReviewsLink({\n googleMapsUri,\n label = 'Read our Google reviews',\n ...anchorProps\n}: GoogleReviewsLinkProps) {\n const href = normalizeGooglePlacePublicUrl(googleMapsUri)\n if (!href) return null\n return createElement(\n 'a',\n {\n ...anchorProps,\n href,\n 'data-brandlab-google-reviews': 'link-only',\n referrerPolicy: 'no-referrer',\n rel: 'noopener noreferrer',\n target: '_blank',\n },\n label,\n )\n}\n\nexport interface GooglePlaceReviewsProps extends HTMLAttributes<HTMLElement> {\n snapshot: GooglePlaceReviewsSnapshot\n reviewClassName?: string\n authorClassName?: string\n avatarClassName?: string\n actionsClassName?: string\n textClassName?: string\n attributionClassName?: string\n /** Styles the required review-ordering notice in full mode. */\n policyClassName?: string\n /** Styles the compact policy and provider-attribution row. */\n policyAttributionClassName?: string\n allReviewsLinkClassName?: string\n allReviewsLinkLabel?: string\n /** Keeps source order or presents up to three five-star reviews from the relevance window. */\n selection?: GooglePlaceReviewsSelection\n /** Selects the approved Google Maps attribution asset for the project background. */\n attributionTone?: 'light' | 'dark'\n /** Text is reserved for interfaces that cannot accommodate the official logo. */\n attributionMode?: 'logo' | 'text-constrained-space'\n}\n\nexport interface GooglePlaceReviewsAttributionProps {\n snapshot: GooglePlaceReviewsAvailableSnapshot\n className?: string\n /** Uses phrasing elements for placement beside inline data. Keep outside links. */\n inline?: boolean\n attributionTone?: NonNullable<GooglePlaceReviewsProps['attributionTone']>\n attributionMode?: NonNullable<GooglePlaceReviewsProps['attributionMode']>\n}\n\nexport interface GooglePlaceReviewAuthorProps {\n review: GooglePlaceReview\n className?: string\n avatarClassName?: string\n}\n\nexport interface GooglePlaceReviewActionsProps {\n review: GooglePlaceReview\n className?: string\n}\n\nexport interface GooglePlaceReviewsPolicyAttributionProps\n extends GooglePlaceReviewsAttributionProps {\n selection?: GooglePlaceReviewsSelection\n policyClassName?: string\n policyAttributionClassName?: string\n}\n\nfunction assertNonEmptyText(value: unknown, field: string) {\n if (typeof value !== 'string' || !value.trim()) {\n throw new Error(`${field} is required for Google Places rendering.`)\n }\n}\n\nfunction assertPublicUrl(value: unknown, field: string, required = false) {\n if (value === undefined && !required) return\n if (typeof value !== 'string' || !normalizeGooglePlacePublicUrl(value)) {\n throw new Error(`${field} must be a credential-free HTTPS URL.`)\n }\n}\n\nfunction assertGooglePlaceReviewsSnapshotIsRenderable(\n snapshot: GooglePlaceReviewsAvailableSnapshot,\n) {\n assertNonEmptyText(snapshot.businessName, 'snapshot.businessName')\n assertPublicUrl(snapshot.googleMapsUri, 'snapshot.googleMapsUri', true)\n if (!['summary', 'full'].includes(snapshot.mode)) {\n throw new Error('snapshot.mode must be summary or full.')\n }\n if (\n snapshot.attribution?.label !== GOOGLE_MAPS_ATTRIBUTION_LABEL ||\n snapshot.attribution?.text !== GOOGLE_MAPS_ATTRIBUTION_TEXT\n ) {\n throw new Error('Google Maps attribution must use the unmodified shared label and text.')\n }\n if (\n !Array.isArray(snapshot.reviews) ||\n snapshot.reviews.length > GOOGLE_PLACE_REVIEWS_MAX_REVIEWS ||\n (snapshot.mode === 'summary' && snapshot.reviews.length > 0)\n ) {\n throw new Error('Google Places review content does not match the declared display mode.')\n }\n if (!Array.isArray(snapshot.thirdPartyAttributions)) {\n throw new Error('snapshot.thirdPartyAttributions is required for provider attribution.')\n }\n\n snapshot.reviews.forEach((review, index) => {\n assertNonEmptyText(review.authorName, `snapshot.reviews[${index}].authorName`)\n assertNonEmptyText(review.text, `snapshot.reviews[${index}].text`)\n assertPublicUrl(review.googleMapsUri, `snapshot.reviews[${index}].googleMapsUri`, true)\n assertPublicUrl(review.authorUri, `snapshot.reviews[${index}].authorUri`)\n assertPublicUrl(review.authorPhotoUri, `snapshot.reviews[${index}].authorPhotoUri`)\n assertPublicUrl(review.flagContentUri, `snapshot.reviews[${index}].flagContentUri`)\n })\n snapshot.thirdPartyAttributions.forEach((item, index) => {\n assertNonEmptyText(item.provider, `snapshot.thirdPartyAttributions[${index}].provider`)\n assertPublicUrl(item.providerUri, `snapshot.thirdPartyAttributions[${index}].providerUri`)\n })\n}\n\nfunction externalLinkProps(href: string) {\n return {\n href,\n referrerPolicy: 'no-referrer' as const,\n rel: 'noopener noreferrer',\n target: '_blank' as const,\n }\n}\n\n/** Reviewer identity. The avatar identifies and links to the author; it is not an actions button. */\nexport function GooglePlaceReviewAuthor({\n review,\n className,\n avatarClassName,\n}: GooglePlaceReviewAuthorProps) {\n const authorUri = normalizeGooglePlacePublicUrl(review.authorUri)\n const authorPhotoUri = normalizeGooglePlacePublicUrl(review.authorPhotoUri)\n const children = [\n authorPhotoUri\n ? createElement('img', {\n alt: '',\n className: avatarClassName,\n decoding: 'async',\n 'data-brandlab-google-review-avatar': 'author',\n height: 40,\n key: 'avatar',\n loading: 'lazy',\n referrerPolicy: 'no-referrer',\n src: authorPhotoUri,\n width: 40,\n })\n : null,\n createElement('span', { key: 'name' }, review.authorName),\n ]\n\n return authorUri\n ? createElement(\n 'a',\n {\n ...externalLinkProps(authorUri),\n className,\n 'data-brandlab-google-review-author': 'profile-link',\n },\n ...children,\n )\n : createElement(\n 'span',\n {\n className,\n 'data-brandlab-google-review-author': 'text',\n },\n ...children,\n )\n}\n\n/** Compact per-review source and reporting actions with no client JavaScript. */\nexport function GooglePlaceReviewActions({\n review,\n className,\n}: GooglePlaceReviewActionsProps) {\n const sourceUrl = normalizeGooglePlacePublicUrl(review.googleMapsUri)\n const flagContentUri = normalizeGooglePlacePublicUrl(review.flagContentUri)\n if (!sourceUrl) return null\n\n return createElement(\n 'details',\n {\n className,\n 'data-brandlab-google-review-actions': 'details',\n },\n createElement(\n 'summary',\n {\n 'aria-label': `Review options for ${review.authorName}`,\n 'data-brandlab-google-review-actions': 'trigger',\n },\n createElement('span', { 'aria-hidden': true }, '•••'),\n ),\n createElement(\n 'div',\n { 'data-brandlab-google-review-actions': 'menu' },\n createElement(\n 'a',\n {\n ...externalLinkProps(sourceUrl),\n 'data-brandlab-google-review-action': 'source',\n },\n 'Read this review on Google Maps',\n ),\n flagContentUri\n ? createElement(\n 'a',\n {\n ...externalLinkProps(flagContentUri),\n 'data-brandlab-google-review-action': 'report',\n },\n 'Report this review to Google',\n )\n : null,\n ),\n )\n}\n\nfunction renderGoogleMapsAttribution(\n attributionUrl: string | undefined,\n mode: NonNullable<GooglePlaceReviewsProps['attributionMode']>,\n tone: NonNullable<GooglePlaceReviewsProps['attributionTone']>,\n) {\n const content = mode === 'logo'\n ? createElement('img', {\n alt: GOOGLE_MAPS_ATTRIBUTION_LABEL,\n decoding: 'async',\n draggable: false,\n height: GOOGLE_MAPS_ATTRIBUTION_LOGO_HEIGHT,\n src: GOOGLE_MAPS_ATTRIBUTION_LOGO_DATA_URL[tone],\n width: GOOGLE_MAPS_ATTRIBUTION_LOGO_WIDTH,\n })\n : createElement(\n 'span',\n {\n 'data-brandlab-google-maps-attribution': 'text-constrained-space',\n translate: 'no' as const,\n },\n GOOGLE_MAPS_ATTRIBUTION_TEXT,\n )\n\n if (!attributionUrl) return content\n return createElement(\n 'a',\n {\n ...externalLinkProps(attributionUrl),\n 'aria-label': GOOGLE_MAPS_ATTRIBUTION_LABEL,\n 'data-brandlab-google-maps-attribution': mode,\n },\n content,\n )\n}\n\nfunction renderReview(\n review: GooglePlaceReview,\n index: number,\n props: GooglePlaceReviewsProps,\n) {\n return createElement(\n 'article',\n { className: props.reviewClassName, key: `${review.authorName}:${review.publishTime ?? index}` },\n createElement(\n 'header',\n null,\n createElement(GooglePlaceReviewAuthor, {\n avatarClassName: props.avatarClassName,\n className: props.authorClassName,\n review,\n }),\n review.rating\n ? createElement(\n 'span',\n { 'aria-label': `${review.rating} out of 5 stars` },\n `${review.rating}/5`,\n )\n : null,\n review.relativePublishTimeDescription\n ? createElement(\n 'time',\n { dateTime: review.publishTime },\n review.relativePublishTimeDescription,\n )\n : null,\n createElement(GooglePlaceReviewActions, {\n className: props.actionsClassName,\n review,\n }),\n ),\n createElement('blockquote', { className: props.textClassName }, createElement('p', null, review.text)),\n )\n}\n\n/** Required provider attribution with no project styling or layout policy. */\nexport function GooglePlaceReviewsAttribution({\n snapshot,\n className,\n inline = false,\n attributionTone = 'light',\n attributionMode = 'logo',\n}: GooglePlaceReviewsAttributionProps) {\n const attributionUrl = normalizeGooglePlacePublicUrl(snapshot.googleMapsUri)\n return createElement(\n inline ? 'span' : 'div',\n {\n className,\n 'data-brandlab-google-reviews-attribution': 'required',\n },\n ...snapshot.thirdPartyAttributions.map((item) => {\n const providerUri = normalizeGooglePlacePublicUrl(item.providerUri)\n return createElement(\n inline ? 'span' : 'p',\n { key: `${item.provider}:${providerUri ?? ''}` },\n 'Data provider: ',\n providerUri\n ? createElement('a', externalLinkProps(providerUri), item.provider)\n : item.provider,\n inline ? ' ' : null,\n )\n }),\n createElement(\n inline ? 'span' : 'p',\n null,\n 'Reviews provided by ',\n renderGoogleMapsAttribution(attributionUrl, attributionMode, attributionTone),\n ),\n )\n}\n\nexport function GooglePlaceReviewsPolicyAttribution({\n snapshot,\n selection = 'relevance',\n className,\n policyClassName,\n policyAttributionClassName,\n inline = false,\n attributionTone = 'light',\n attributionMode = 'logo',\n}: GooglePlaceReviewsPolicyAttributionProps) {\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n const policy = snapshot.mode === 'full' && snapshot.reviews.length > 0\n ? normalizedSelection === 'five-star-featured'\n ? \"Showing 5-star reviews selected from Google's relevance-ranked results.\"\n : 'Google Maps reviews are ordered by relevance.'\n : null\n\n return createElement(\n inline ? 'span' : 'div',\n {\n className: policyAttributionClassName,\n 'data-brandlab-google-review-selection': normalizedSelection,\n 'data-brandlab-google-reviews-policy-attribution': 'compact',\n },\n policy\n ? createElement(\n inline ? 'span' : 'p',\n {\n className: policyClassName,\n 'data-brandlab-google-review-ordering': normalizedSelection,\n },\n inline ? `${policy} ` : policy,\n )\n : null,\n createElement(GooglePlaceReviewsAttribution, {\n inline,\n attributionMode,\n attributionTone,\n className,\n snapshot,\n }),\n )\n}\n\n/**\n * Minimal, unstyled Places output. Projects may use this semantic renderer or\n * render a validated snapshot themselves through GooglePlaceReviewsClient.\n */\nexport function GooglePlaceReviews({\n snapshot,\n reviewClassName,\n authorClassName,\n avatarClassName,\n actionsClassName,\n textClassName,\n attributionClassName,\n policyClassName,\n policyAttributionClassName,\n allReviewsLinkClassName,\n allReviewsLinkLabel = 'Read all reviews on Google Maps',\n selection = 'relevance',\n attributionTone = 'light',\n attributionMode = 'logo',\n ...sectionProps\n}: GooglePlaceReviewsProps) {\n if (snapshot.status !== 'available') return null\n assertGooglePlaceReviewsSnapshotIsRenderable(snapshot)\n const normalizedSelection = normalizeGooglePlaceReviewsSelection(selection)\n if (normalizedSelection === 'five-star-featured' && snapshot.mode !== 'full') {\n throw new Error('Five-star featured reviews require full mode.')\n }\n const displayedSnapshot = selectGooglePlaceReviewsSnapshot(snapshot, normalizedSelection)\n const props = {\n ...sectionProps,\n snapshot: displayedSnapshot,\n reviewClassName,\n authorClassName,\n avatarClassName,\n actionsClassName,\n textClassName,\n attributionClassName,\n attributionTone,\n attributionMode,\n }\n return createElement(\n 'section',\n {\n ...sectionProps,\n 'aria-label': sectionProps['aria-label'] ?? `${snapshot.businessName} reviews on Google Maps`,\n 'data-brandlab-google-reviews': `attribution-complete-${snapshot.mode}`,\n 'data-brandlab-google-attribution-mode': attributionMode,\n 'data-brandlab-google-review-count': displayedSnapshot.reviews.length,\n 'data-brandlab-google-review-selection': normalizedSelection,\n },\n snapshot.rating\n ? createElement(\n 'p',\n {\n 'aria-label': `Average rating ${snapshot.rating} out of 5${\n snapshot.userRatingCount === undefined ? '' : ` from ${snapshot.userRatingCount} reviews`\n }`,\n },\n `${snapshot.rating}/5${\n snapshot.userRatingCount === undefined ? '' : ` from ${snapshot.userRatingCount} reviews`\n }`,\n )\n : null,\n ...displayedSnapshot.reviews.map((review, index) => renderReview(review, index, props)),\n normalizedSelection === 'five-star-featured' && displayedSnapshot.reviews.length === 0\n ? createElement(GoogleReviewsLink, {\n className: allReviewsLinkClassName,\n googleMapsUri: displayedSnapshot.googleMapsUri,\n label: allReviewsLinkLabel,\n })\n : null,\n createElement(GooglePlaceReviewsPolicyAttribution, {\n attributionMode,\n attributionTone,\n className: attributionClassName,\n policyAttributionClassName,\n policyClassName,\n selection: normalizedSelection,\n snapshot: displayedSnapshot,\n }),\n )\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { type BrandlabAnalyticsContract } from '@brandlab-digital/site-core/analytics';
1
+ /** Supplied by `defineBrandlabAnalytics(...).googleTag`. */
2
2
  export interface BrandlabGoogleTagConfig {
3
3
  enabled: boolean;
4
4
  measurementId?: string | null;
@@ -12,8 +12,5 @@ export interface BrandlabGoogleTagPlan {
12
12
  destinations: readonly string[];
13
13
  websiteCallDestination: string | null;
14
14
  }
15
- export declare function resolveBrandlabGoogleTagConfig(contract: BrandlabAnalyticsContract, environment: Readonly<Record<string, string | undefined>>, options: {
16
- enabled: boolean;
17
- }): BrandlabGoogleTagConfig;
18
15
  export declare function createBrandlabGoogleTagPlan(config: BrandlabGoogleTagConfig, phoneNumber?: string | null): BrandlabGoogleTagPlan | null;
19
16
  //# sourceMappingURL=google-tag-plan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-tag-plan.d.ts","sourceRoot":"","sources":["../src/google-tag-plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,uCAAuC,CAAA;AAE9C,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,mCAAmC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACpD;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC;AAKD,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,yBAAyB,EACnC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACzD,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAC5B,uBAAuB,CAYzB;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,uBAAuB,EAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,qBAAqB,GAAG,IAAI,CA2C9B"}
1
+ {"version":3,"file":"google-tag-plan.d.ts","sourceRoot":"","sources":["../src/google-tag-plan.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,mCAAmC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACpD;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IAC/B,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;CACtC;AAKD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,uBAAuB,EAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,qBAAqB,GAAG,IAAI,CA2C9B"}
@@ -1,19 +1,6 @@
1
- import { defineAnalyticsContract, getGoogleAdsWebsiteCallSendTo, } from '@brandlab-digital/site-core/analytics';
1
+ import { getGoogleAdsWebsiteCallSendTo } from '@brandlab-digital/site-core/analytics';
2
2
  const GA4_MEASUREMENT_ID_PATTERN = /^G-[A-Z0-9]{4,20}$/i;
3
3
  const GOOGLE_ADS_CONVERSION_ID_PATTERN = /^(?:AW-)?\d{6,20}$/;
4
- export function resolveBrandlabGoogleTagConfig(contract, environment, options) {
5
- defineAnalyticsContract(contract);
6
- return {
7
- enabled: options.enabled,
8
- measurementId: environment[contract.measurementIdEnv],
9
- googleAdsConversionId: contract.googleAds
10
- ? environment[contract.googleAds.conversionIdEnv]
11
- : undefined,
12
- googleAdsWebsiteCallConversionLabel: contract.googleAds?.websiteCalls
13
- ? environment[contract.googleAds.websiteCalls.conversionLabelEnv]
14
- : undefined,
15
- };
16
- }
17
4
  export function createBrandlabGoogleTagPlan(config, phoneNumber) {
18
5
  if (!config.enabled)
19
6
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"google-tag-plan.js","sourceRoot":"","sources":["../src/google-tag-plan.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n defineAnalyticsContract,\n getGoogleAdsWebsiteCallSendTo,\n type BrandlabAnalyticsContract,\n} from '@brandlab-digital/site-core/analytics'\n\nexport interface BrandlabGoogleTagConfig {\n enabled: boolean\n measurementId?: string | null\n googleAdsConversionId?: string | null\n googleAdsWebsiteCallConversionLabel?: string | null\n}\n\nexport interface BrandlabGoogleTagPlan {\n loaderId: string\n source: string\n inlineScript: string\n destinations: readonly string[]\n websiteCallDestination: string | null\n}\n\nconst GA4_MEASUREMENT_ID_PATTERN = /^G-[A-Z0-9]{4,20}$/i\nconst GOOGLE_ADS_CONVERSION_ID_PATTERN = /^(?:AW-)?\\d{6,20}$/\n\nexport function resolveBrandlabGoogleTagConfig(\n contract: BrandlabAnalyticsContract,\n environment: Readonly<Record<string, string | undefined>>,\n options: { enabled: boolean },\n): BrandlabGoogleTagConfig {\n defineAnalyticsContract(contract)\n return {\n enabled: options.enabled,\n measurementId: environment[contract.measurementIdEnv],\n googleAdsConversionId: contract.googleAds\n ? environment[contract.googleAds.conversionIdEnv]\n : undefined,\n googleAdsWebsiteCallConversionLabel: contract.googleAds?.websiteCalls\n ? environment[contract.googleAds.websiteCalls.conversionLabelEnv]\n : undefined,\n }\n}\n\nexport function createBrandlabGoogleTagPlan(\n config: BrandlabGoogleTagConfig,\n phoneNumber?: string | null,\n): BrandlabGoogleTagPlan | null {\n if (!config.enabled) return null\n const measurementId = validMeasurementId(config.measurementId)\n const googleAdsConversionId = validGoogleAdsConversionId(config.googleAdsConversionId)\n const loaderId = measurementId ?? googleAdsConversionId\n if (!loaderId) return null\n\n const destinations = [...new Set([\n ...(measurementId ? [measurementId] : []),\n ...(googleAdsConversionId ? [googleAdsConversionId] : []),\n ])]\n const displayPhone = safeDisplayedBusinessPhone(phoneNumber)\n const websiteCallDestination = displayPhone\n ? getGoogleAdsWebsiteCallSendTo({\n conversionId: googleAdsConversionId,\n conversionLabel: config.googleAdsWebsiteCallConversionLabel,\n }) ?? null\n : null\n const configCommands = destinations.map(\n (destination) => `window.gtag('config', ${safeJson(destination)});`,\n )\n if (websiteCallDestination && displayPhone) {\n configCommands.push(\n `window.gtag('config', ${safeJson(websiteCallDestination)}, ${safeJson({\n phone_conversion_number: displayPhone,\n })});`,\n )\n }\n\n return {\n loaderId,\n source: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(loaderId)}`,\n inlineScript: [\n 'window.dataLayer = window.dataLayer || [];',\n 'window.gtag = window.gtag || function(){window.dataLayer.push(arguments);};',\n \"window.gtag('consent', 'default', {ad_user_data:'denied',ad_personalization:'denied'});\",\n \"window.gtag('set', 'user_data', {});\",\n \"window.gtag('js', new Date());\",\n ...configCommands,\n ].join('\\n'),\n destinations,\n websiteCallDestination,\n }\n}\n\nfunction validMeasurementId(value: string | null | undefined) {\n const normalized = value?.trim()\n return normalized && GA4_MEASUREMENT_ID_PATTERN.test(normalized)\n ? normalized.toUpperCase()\n : undefined\n}\n\nfunction validGoogleAdsConversionId(value: string | null | undefined) {\n const normalized = value?.trim()\n if (!normalized || !GOOGLE_ADS_CONVERSION_ID_PATTERN.test(normalized)) return undefined\n return normalized.startsWith('AW-') ? normalized : `AW-${normalized}`\n}\n\nfunction safeDisplayedBusinessPhone(value: string | null | undefined) {\n const normalized = value?.trim()\n const digits = normalized?.replace(/\\D/g, '') ?? ''\n return normalized &&\n normalized.length <= 32 &&\n digits.length >= 6 &&\n /^[0-9+().\\s-]+$/.test(normalized)\n ? normalized\n : undefined\n}\n\nfunction safeJson(value: unknown) {\n return JSON.stringify(value)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029')\n}\n"]}
1
+ {"version":3,"file":"google-tag-plan.js","sourceRoot":"","sources":["../src/google-tag-plan.ts"],"names":[],"mappings":"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","sourcesContent":["import { getGoogleAdsWebsiteCallSendTo } from '@brandlab-digital/site-core/analytics'\n\n/** Supplied by `defineBrandlabAnalytics(...).googleTag`. */\nexport interface BrandlabGoogleTagConfig {\n enabled: boolean\n measurementId?: string | null\n googleAdsConversionId?: string | null\n googleAdsWebsiteCallConversionLabel?: string | null\n}\n\nexport interface BrandlabGoogleTagPlan {\n loaderId: string\n source: string\n inlineScript: string\n destinations: readonly string[]\n websiteCallDestination: string | null\n}\n\nconst GA4_MEASUREMENT_ID_PATTERN = /^G-[A-Z0-9]{4,20}$/i\nconst GOOGLE_ADS_CONVERSION_ID_PATTERN = /^(?:AW-)?\\d{6,20}$/\n\nexport function createBrandlabGoogleTagPlan(\n config: BrandlabGoogleTagConfig,\n phoneNumber?: string | null,\n): BrandlabGoogleTagPlan | null {\n if (!config.enabled) return null\n const measurementId = validMeasurementId(config.measurementId)\n const googleAdsConversionId = validGoogleAdsConversionId(config.googleAdsConversionId)\n const loaderId = measurementId ?? googleAdsConversionId\n if (!loaderId) return null\n\n const destinations = [...new Set([\n ...(measurementId ? [measurementId] : []),\n ...(googleAdsConversionId ? [googleAdsConversionId] : []),\n ])]\n const displayPhone = safeDisplayedBusinessPhone(phoneNumber)\n const websiteCallDestination = displayPhone\n ? getGoogleAdsWebsiteCallSendTo({\n conversionId: googleAdsConversionId,\n conversionLabel: config.googleAdsWebsiteCallConversionLabel,\n }) ?? null\n : null\n const configCommands = destinations.map(\n (destination) => `window.gtag('config', ${safeJson(destination)});`,\n )\n if (websiteCallDestination && displayPhone) {\n configCommands.push(\n `window.gtag('config', ${safeJson(websiteCallDestination)}, ${safeJson({\n phone_conversion_number: displayPhone,\n })});`,\n )\n }\n\n return {\n loaderId,\n source: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(loaderId)}`,\n inlineScript: [\n 'window.dataLayer = window.dataLayer || [];',\n 'window.gtag = window.gtag || function(){window.dataLayer.push(arguments);};',\n \"window.gtag('consent', 'default', {ad_user_data:'denied',ad_personalization:'denied'});\",\n \"window.gtag('set', 'user_data', {});\",\n \"window.gtag('js', new Date());\",\n ...configCommands,\n ].join('\\n'),\n destinations,\n websiteCallDestination,\n }\n}\n\nfunction validMeasurementId(value: string | null | undefined) {\n const normalized = value?.trim()\n return normalized && GA4_MEASUREMENT_ID_PATTERN.test(normalized)\n ? normalized.toUpperCase()\n : undefined\n}\n\nfunction validGoogleAdsConversionId(value: string | null | undefined) {\n const normalized = value?.trim()\n if (!normalized || !GOOGLE_ADS_CONVERSION_ID_PATTERN.test(normalized)) return undefined\n return normalized.startsWith('AW-') ? normalized : `AW-${normalized}`\n}\n\nfunction safeDisplayedBusinessPhone(value: string | null | undefined) {\n const normalized = value?.trim()\n const digits = normalized?.replace(/\\D/g, '') ?? ''\n return normalized &&\n normalized.length <= 32 &&\n digits.length >= 6 &&\n /^[0-9+().\\s-]+$/.test(normalized)\n ? normalized\n : undefined\n}\n\nfunction safeJson(value: unknown) {\n return JSON.stringify(value)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029')\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { type BrandlabGoogleTagConfig } from './google-tag-plan.js';
2
- export { createBrandlabGoogleTagPlan, resolveBrandlabGoogleTagConfig, } from './google-tag-plan.js';
2
+ export { createBrandlabGoogleTagPlan } from './google-tag-plan.js';
3
3
  export type { BrandlabGoogleTagConfig, BrandlabGoogleTagPlan, } from './google-tag-plan.js';
4
4
  export interface BrandlabGoogleTagProps extends BrandlabGoogleTagConfig {
5
5
  /** Must match the verified public number exactly as it is rendered on the page. */
@@ -9,9 +9,10 @@ export interface BrandlabGoogleTagProps extends BrandlabGoogleTagConfig {
9
9
  /**
10
10
  * Shared Google tag and website-call forwarding-number snippet.
11
11
  *
12
- * Render this exactly once from the root layout. The enabled flag remains the
13
- * project consent/production gate; account-side conversion settings remain
14
- * outside website runtime.
12
+ * Render this exactly once from the root layout:
13
+ * `<BrandlabGoogleTag {...analytics.googleTag} phoneNumber={displayedPhone} />`.
14
+ * `analytics.googleTag.enabled` is true only on the production deployment;
15
+ * account-side conversion settings remain outside website runtime.
15
16
  */
16
17
  export declare function BrandlabGoogleTag(props: BrandlabGoogleTagProps): import("react/jsx-runtime").JSX.Element | null;
17
18
  //# sourceMappingURL=google-tag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-tag.d.ts","sourceRoot":"","sources":["../src/google-tag.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAA;AAC7B,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACrE,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,kDAqB9D"}
1
+ {"version":3,"file":"google-tag.d.ts","sourceRoot":"","sources":["../src/google-tag.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAA;AAClE,YAAY,EACV,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,sBAAuB,SAAQ,uBAAuB;IACrE,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,kDAqB9D"}
@@ -1,13 +1,14 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Script from 'next/script';
3
3
  import { createBrandlabGoogleTagPlan, } from './google-tag-plan.js';
4
- export { createBrandlabGoogleTagPlan, resolveBrandlabGoogleTagConfig, } from './google-tag-plan.js';
4
+ export { createBrandlabGoogleTagPlan } from './google-tag-plan.js';
5
5
  /**
6
6
  * Shared Google tag and website-call forwarding-number snippet.
7
7
  *
8
- * Render this exactly once from the root layout. The enabled flag remains the
9
- * project consent/production gate; account-side conversion settings remain
10
- * outside website runtime.
8
+ * Render this exactly once from the root layout:
9
+ * `<BrandlabGoogleTag {...analytics.googleTag} phoneNumber={displayedPhone} />`.
10
+ * `analytics.googleTag.enabled` is true only on the production deployment;
11
+ * account-side conversion settings remain outside website runtime.
11
12
  */
12
13
  export function BrandlabGoogleTag(props) {
13
14
  const plan = createBrandlabGoogleTagPlan(props, props.phoneNumber);
@@ -1 +1 @@
1
- {"version":3,"file":"google-tag.js","sourceRoot":"","sources":["../src/google-tag.tsx"],"names":[],"mappings":";AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EACL,2BAA2B,GAE5B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAA;AAY7B;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,IAAI,GAAG,2BAA2B,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IAClE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,OAAO,CACL,8BACE,KAAC,MAAM,IACL,EAAE,EAAC,4BAA4B,8BACN,QAAQ,EACjC,GAAG,EAAE,IAAI,CAAC,MAAM,EAChB,QAAQ,EAAC,kBAAkB,EAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,GAClB,EACF,KAAC,MAAM,IACL,EAAE,EAAC,4BAA4B,8BACN,QAAQ,EACjC,QAAQ,EAAC,kBAAkB,EAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,GACtD,IACD,CACJ,CAAA;AACH,CAAC","sourcesContent":["import Script from 'next/script'\nimport {\n createBrandlabGoogleTagPlan,\n type BrandlabGoogleTagConfig,\n} from './google-tag-plan.js'\n\nexport {\n createBrandlabGoogleTagPlan,\n resolveBrandlabGoogleTagConfig,\n} from './google-tag-plan.js'\nexport type {\n BrandlabGoogleTagConfig,\n BrandlabGoogleTagPlan,\n} from './google-tag-plan.js'\n\nexport interface BrandlabGoogleTagProps extends BrandlabGoogleTagConfig {\n /** Must match the verified public number exactly as it is rendered on the page. */\n phoneNumber?: string | null\n nonce?: string\n}\n\n/**\n * Shared Google tag and website-call forwarding-number snippet.\n *\n * Render this exactly once from the root layout. The enabled flag remains the\n * project consent/production gate; account-side conversion settings remain\n * outside website runtime.\n */\nexport function BrandlabGoogleTag(props: BrandlabGoogleTagProps) {\n const plan = createBrandlabGoogleTagPlan(props, props.phoneNumber)\n if (!plan) return null\n return (\n <>\n <Script\n id=\"brandlab-google-tag-loader\"\n data-brandlab-google-tag=\"loader\"\n src={plan.source}\n strategy=\"afterInteractive\"\n nonce={props.nonce}\n />\n <Script\n id=\"brandlab-google-tag-config\"\n data-brandlab-google-tag=\"config\"\n strategy=\"afterInteractive\"\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: plan.inlineScript }}\n />\n </>\n )\n}\n"]}
1
+ {"version":3,"file":"google-tag.js","sourceRoot":"","sources":["../src/google-tag.tsx"],"names":[],"mappings":";AAAA,OAAO,MAAM,MAAM,aAAa,CAAA;AAChC,OAAO,EACL,2BAA2B,GAE5B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAA;AAYlE;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAA6B;IAC7D,MAAM,IAAI,GAAG,2BAA2B,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAA;IAClE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAA;IACtB,OAAO,CACL,8BACE,KAAC,MAAM,IACL,EAAE,EAAC,4BAA4B,8BACN,QAAQ,EACjC,GAAG,EAAE,IAAI,CAAC,MAAM,EAChB,QAAQ,EAAC,kBAAkB,EAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,GAClB,EACF,KAAC,MAAM,IACL,EAAE,EAAC,4BAA4B,8BACN,QAAQ,EACjC,QAAQ,EAAC,kBAAkB,EAC3B,KAAK,EAAE,KAAK,CAAC,KAAK,EAClB,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,GACtD,IACD,CACJ,CAAA;AACH,CAAC","sourcesContent":["import Script from 'next/script'\nimport {\n createBrandlabGoogleTagPlan,\n type BrandlabGoogleTagConfig,\n} from './google-tag-plan.js'\n\nexport { createBrandlabGoogleTagPlan } from './google-tag-plan.js'\nexport type {\n BrandlabGoogleTagConfig,\n BrandlabGoogleTagPlan,\n} from './google-tag-plan.js'\n\nexport interface BrandlabGoogleTagProps extends BrandlabGoogleTagConfig {\n /** Must match the verified public number exactly as it is rendered on the page. */\n phoneNumber?: string | null\n nonce?: string\n}\n\n/**\n * Shared Google tag and website-call forwarding-number snippet.\n *\n * Render this exactly once from the root layout:\n * `<BrandlabGoogleTag {...analytics.googleTag} phoneNumber={displayedPhone} />`.\n * `analytics.googleTag.enabled` is true only on the production deployment;\n * account-side conversion settings remain outside website runtime.\n */\nexport function BrandlabGoogleTag(props: BrandlabGoogleTagProps) {\n const plan = createBrandlabGoogleTagPlan(props, props.phoneNumber)\n if (!plan) return null\n return (\n <>\n <Script\n id=\"brandlab-google-tag-loader\"\n data-brandlab-google-tag=\"loader\"\n src={plan.source}\n strategy=\"afterInteractive\"\n nonce={props.nonce}\n />\n <Script\n id=\"brandlab-google-tag-config\"\n data-brandlab-google-tag=\"config\"\n strategy=\"afterInteractive\"\n nonce={props.nonce}\n dangerouslySetInnerHTML={{ __html: plan.inlineScript }}\n />\n </>\n )\n}\n"]}