keystone-design-bootstrap 1.0.97 → 1.0.99
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/contexts/index.js +134 -1
- package/dist/contexts/index.js.map +1 -1
- package/dist/design_system/components/DynamicFormFields.js +130 -3
- package/dist/design_system/components/DynamicFormFields.js.map +1 -1
- package/dist/design_system/elements/index.js +130 -3
- package/dist/design_system/elements/index.js.map +1 -1
- package/dist/design_system/sections/index.js +150 -9
- package/dist/design_system/sections/index.js.map +1 -1
- package/dist/index.js +184 -21
- package/dist/index.js.map +1 -1
- package/dist/lib/server-api.js +49 -2
- package/dist/lib/server-api.js.map +1 -1
- package/dist/tracking/index.js +212 -185
- package/dist/tracking/index.js.map +1 -1
- package/package.json +1 -1
- package/src/contexts/ThemeContext.tsx +2 -1
- package/src/design_system/chat/useRealtimeReplyOrchestrator.ts +24 -5
- package/src/design_system/components/ChatWidget.tsx +10 -3
- package/src/design_system/elements/map/GoogleMap.tsx +9 -2
- package/src/design_system/sections/blog-post.tsx +13 -3
- package/src/design_system/sections/home-hero-component.tsx +4 -1
- package/src/lib/server-api.ts +6 -2
- package/src/lib/server-log.ts +39 -0
- package/src/next/routes/chat.ts +3 -2
- package/src/next/routes/form.ts +2 -1
- package/src/tracking/MetaPixel.tsx +10 -1
- package/src/tracking/firePixelEvent.ts +7 -2
- package/src/tracking/logging.ts +39 -6
package/dist/contexts/index.js
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
|
|
1
18
|
// src/contexts/ThemeContext.tsx
|
|
2
19
|
import { createContext, useContext } from "react";
|
|
3
20
|
|
|
@@ -18,6 +35,122 @@ function isValidTheme(theme) {
|
|
|
18
35
|
return theme in THEME_CONFIG;
|
|
19
36
|
}
|
|
20
37
|
|
|
38
|
+
// src/tracking/logging.ts
|
|
39
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
40
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
41
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
42
|
+
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
43
|
+
var BUILD_CONSOLE_DISABLED = process.env.NEXT_PUBLIC_LOGGING_DISABLED === "1";
|
|
44
|
+
var BUILD_POSTHOG_DISABLED = process.env.NEXT_PUBLIC_POSTHOG_LOGGING_DISABLED === "1";
|
|
45
|
+
var MAX_PENDING_POSTHOG_LOGS = 500;
|
|
46
|
+
var otelLogger = null;
|
|
47
|
+
var pendingPostHogLogs = [];
|
|
48
|
+
var browserConsole = globalThis == null ? void 0 : globalThis["console"];
|
|
49
|
+
var CHANNEL_COLORS = {
|
|
50
|
+
// Shared diagnostics
|
|
51
|
+
"global-client": "#d2a8ff",
|
|
52
|
+
// Section pins (desktop)
|
|
53
|
+
"every-channel-pin": "#9febd7",
|
|
54
|
+
"hero-pin": "#6ecc8b",
|
|
55
|
+
"pricing-pin": "#399587",
|
|
56
|
+
"product-screens-pin": "#4fafa0",
|
|
57
|
+
"social-proof-pin": "#ffbb8a",
|
|
58
|
+
"value-props-pin": "#e0a733",
|
|
59
|
+
"work-pin": "#f57e56",
|
|
60
|
+
// Section pins (mobile)
|
|
61
|
+
"mobile-every-channel-pin": "#7ed9c6",
|
|
62
|
+
"mobile-hero-pin": "#f0eee6",
|
|
63
|
+
"mobile-pricing-pin": "#80d4ff",
|
|
64
|
+
"mobile-product-screens-pin": "#3a9085",
|
|
65
|
+
"mobile-social-proof-pin": "#ffd580",
|
|
66
|
+
"mobile-value-props-pin": "#4fafa0"
|
|
67
|
+
};
|
|
68
|
+
function flattenAttributes(input, prefix = "") {
|
|
69
|
+
const output = {};
|
|
70
|
+
for (const [key, value] of Object.entries(input)) {
|
|
71
|
+
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
72
|
+
if (value === null || value === void 0) continue;
|
|
73
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
74
|
+
output[nextKey] = value;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
output[nextKey] = JSON.stringify(value);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (typeof value === "object") {
|
|
82
|
+
Object.assign(output, flattenAttributes(value, nextKey));
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
output[nextKey] = String(value);
|
|
86
|
+
}
|
|
87
|
+
return output;
|
|
88
|
+
}
|
|
89
|
+
function enqueuePendingPostHogLog(entry) {
|
|
90
|
+
if (pendingPostHogLogs.length >= MAX_PENDING_POSTHOG_LOGS) {
|
|
91
|
+
pendingPostHogLogs.shift();
|
|
92
|
+
}
|
|
93
|
+
pendingPostHogLogs.push(entry);
|
|
94
|
+
}
|
|
95
|
+
function isConsoleEnabled() {
|
|
96
|
+
if (BUILD_CONSOLE_DISABLED) return false;
|
|
97
|
+
if (typeof window === "undefined") return true;
|
|
98
|
+
return window.__loggingDisabled !== true;
|
|
99
|
+
}
|
|
100
|
+
function isPostHogShippingEnabled() {
|
|
101
|
+
if (BUILD_POSTHOG_DISABLED) return false;
|
|
102
|
+
if (typeof window === "undefined") return false;
|
|
103
|
+
return window.__posthogLoggingDisabled !== true;
|
|
104
|
+
}
|
|
105
|
+
function formatDetail(detail) {
|
|
106
|
+
return Object.entries(detail).map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : String(v)}`).join(" ");
|
|
107
|
+
}
|
|
108
|
+
function emitConsole(level, channel, event, detail) {
|
|
109
|
+
var _a, _b, _c, _d;
|
|
110
|
+
const color = (_a = CHANNEL_COLORS[channel]) != null ? _a : "#aaa";
|
|
111
|
+
const detailStr = formatDetail(detail);
|
|
112
|
+
const message = `%c[${channel}] %c${event}%c ${detailStr}`;
|
|
113
|
+
const channelStyle = `color:${color}; font-weight:bold`;
|
|
114
|
+
const eventStyle = level === "error" ? "color:#e94e4e; font-weight:bold" : level === "warn" ? "color:#f5a623; font-weight:bold" : "color:#fff; font-weight:bold";
|
|
115
|
+
const detailStyle = "color:#999; font-weight:normal";
|
|
116
|
+
if (level === "error") {
|
|
117
|
+
(_b = browserConsole == null ? void 0 : browserConsole.error) == null ? void 0 : _b.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (level === "warn") {
|
|
121
|
+
(_c = browserConsole == null ? void 0 : browserConsole.warn) == null ? void 0 : _c.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
(_d = browserConsole == null ? void 0 : browserConsole.log) == null ? void 0 : _d.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
125
|
+
}
|
|
126
|
+
function emitToPostHog(level, channel, event, detail) {
|
|
127
|
+
if (!otelLogger) return false;
|
|
128
|
+
const severityText = level === "warn" ? "WARNING" : level === "error" ? "ERROR" : "INFO";
|
|
129
|
+
const attributes = flattenAttributes(__spreadValues({ channel }, detail));
|
|
130
|
+
otelLogger.emit({
|
|
131
|
+
severityText,
|
|
132
|
+
body: event,
|
|
133
|
+
attributes
|
|
134
|
+
});
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
function emit(level, channel, event, detail, options) {
|
|
138
|
+
var _a;
|
|
139
|
+
const shouldShip = ((_a = options == null ? void 0 : options.shipToPostHog) != null ? _a : level !== "info") && isPostHogShippingEnabled();
|
|
140
|
+
if (level !== "info" || isConsoleEnabled()) {
|
|
141
|
+
emitConsole(level, channel, event, detail);
|
|
142
|
+
}
|
|
143
|
+
if (shouldShip) {
|
|
144
|
+
const shipped = emitToPostHog(level, channel, event, detail);
|
|
145
|
+
if (!shipped) {
|
|
146
|
+
enqueuePendingPostHogLog({ level, channel, event, detail });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function warn(channel, event, detail = {}, options) {
|
|
151
|
+
emit("warn", channel, event, detail, options);
|
|
152
|
+
}
|
|
153
|
+
|
|
21
154
|
// src/contexts/ThemeContext.tsx
|
|
22
155
|
var ThemeContext = createContext({ theme: "classic" });
|
|
23
156
|
function ThemeProvider({
|
|
@@ -25,7 +158,7 @@ function ThemeProvider({
|
|
|
25
158
|
children
|
|
26
159
|
}) {
|
|
27
160
|
if (!isValidTheme(theme)) {
|
|
28
|
-
|
|
161
|
+
warn("theme", "INVALID_THEME_FALLBACK", { theme });
|
|
29
162
|
theme = "classic";
|
|
30
163
|
}
|
|
31
164
|
return /* @__PURE__ */ React.createElement(ThemeContext.Provider, { value: { theme } }, children);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contexts/ThemeContext.tsx","../../src/themes/index.ts"],"sourcesContent":["'use client';\n\nimport { createContext, useContext } from 'react';\nimport { Theme, isValidTheme } from '../themes';\n\ninterface ThemeContextValue {\n theme: Theme;\n}\n\nconst ThemeContext = createContext<ThemeContextValue>({ theme: 'classic' });\n\nexport function ThemeProvider({ \n theme, \n children \n}: { \n theme: Theme; \n children: React.ReactNode;\n}) {\n // Validate theme at runtime\n if (!isValidTheme(theme)) {\n console.warn(`Invalid theme \"${theme}\", falling back to \"classic\"`);\n theme = 'classic';\n }\n \n return (\n <ThemeContext.Provider value={{ theme }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n","/**\n * Theme Configuration\n * Single source of truth for all themes\n */\n\nexport const THEME_CONFIG = {\n classic: '', // Base files with no suffix (hero-home.tsx)\n aman: '.aman', // Aman Hotels variant files (hero-home.aman.tsx)\n barelux: '.barelux', // Bare Lux Studio variant files (hero-home.barelux.tsx)\n balance: '.balance', // Balance Aesthetics variant files (hero-home.balance.tsx)\n custom: '', // Fully custom sites — no design-system CSS loaded, all styling built in the site itself\n} as const;\n\nexport type Theme = keyof typeof THEME_CONFIG;\n\nexport function getAvailableThemes(): Theme[] {\n return Object.keys(THEME_CONFIG) as Theme[];\n}\n\nexport function getThemeSuffix(theme: Theme): string {\n return THEME_CONFIG[theme] || '';\n}\n\nexport function isValidTheme(theme: string): theme is Theme {\n return theme in THEME_CONFIG;\n}\n"],"mappings":";AAEA,SAAS,eAAe,kBAAkB;;;ACGnC,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA;AAAA,EACT,MAAM;AAAA;AAAA,EACN,SAAS;AAAA;AAAA,EACT,SAAS;AAAA;AAAA,EACT,QAAQ;AAAA;AACV;AAYO,SAAS,aAAa,OAA+B;AAC1D,SAAO,SAAS;AAClB;;;ADhBA,IAAM,eAAe,cAAiC,EAAE,OAAO,UAAU,CAAC;AAEnE,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AACF,GAGG;AAED,MAAI,CAAC,aAAa,KAAK,GAAG;AACxB,YAAQ,KAAK,kBAAkB,KAAK,8BAA8B;AAClE,YAAQ;AAAA,EACV;AAEA,SACE,oCAAC,aAAa,UAAb,EAAsB,OAAO,EAAE,MAAM,KACnC,QACH;AAEJ;AAEO,SAAS,WAAW;AACzB,SAAO,WAAW,YAAY;AAChC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/contexts/ThemeContext.tsx","../../src/themes/index.ts","../../src/tracking/logging.ts"],"sourcesContent":["'use client';\n\nimport { createContext, useContext } from 'react';\nimport { Theme, isValidTheme } from '../themes';\nimport { warn } from '../tracking/logging';\n\ninterface ThemeContextValue {\n theme: Theme;\n}\n\nconst ThemeContext = createContext<ThemeContextValue>({ theme: 'classic' });\n\nexport function ThemeProvider({ \n theme, \n children \n}: { \n theme: Theme; \n children: React.ReactNode;\n}) {\n // Validate theme at runtime\n if (!isValidTheme(theme)) {\n warn('theme', 'INVALID_THEME_FALLBACK', { theme });\n theme = 'classic';\n }\n \n return (\n <ThemeContext.Provider value={{ theme }}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\nexport function useTheme() {\n return useContext(ThemeContext);\n}\n","/**\n * Theme Configuration\n * Single source of truth for all themes\n */\n\nexport const THEME_CONFIG = {\n classic: '', // Base files with no suffix (hero-home.tsx)\n aman: '.aman', // Aman Hotels variant files (hero-home.aman.tsx)\n barelux: '.barelux', // Bare Lux Studio variant files (hero-home.barelux.tsx)\n balance: '.balance', // Balance Aesthetics variant files (hero-home.balance.tsx)\n custom: '', // Fully custom sites — no design-system CSS loaded, all styling built in the site itself\n} as const;\n\nexport type Theme = keyof typeof THEME_CONFIG;\n\nexport function getAvailableThemes(): Theme[] {\n return Object.keys(THEME_CONFIG) as Theme[];\n}\n\nexport function getThemeSuffix(theme: Theme): string {\n return THEME_CONFIG[theme] || '';\n}\n\nexport function isValidTheme(theme: string): theme is Theme {\n return theme in THEME_CONFIG;\n}\n","'use client';\n\nimport { logs } from '@opentelemetry/api-logs';\nimport { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';\n\nconst BUILD_CONSOLE_DISABLED = process.env.NEXT_PUBLIC_LOGGING_DISABLED === '1';\nconst BUILD_POSTHOG_DISABLED = process.env.NEXT_PUBLIC_POSTHOG_LOGGING_DISABLED === '1';\ninterface LoggingWindow extends Window {\n __loggingDisabled?: boolean;\n __posthogLoggingDisabled?: boolean;\n}\n\nexport type LogLevel = 'info' | 'warn' | 'error';\n\nexport type LogOptions = {\n /** Send this log payload to PostHog Logs product. */\n shipToPostHog?: boolean;\n};\n\ntype OTelInitOptions = {\n apiKey: string;\n apiHost?: string;\n serviceName?: string;\n environment?: string;\n accountId?: number;\n accountName?: string;\n};\n\ntype PendingShipLog = {\n level: LogLevel;\n channel: string;\n event: string;\n detail: Record<string, unknown>;\n};\n\nconst MAX_PENDING_POSTHOG_LOGS = 500;\nlet otelProvider: LoggerProvider | null = null;\nlet otelLogger: ReturnType<typeof logs.getLogger> | null = null;\nlet otelInitFingerprint = '';\nconst pendingPostHogLogs: PendingShipLog[] = [];\nconst browserConsole = globalThis?.['console'];\n\n/**\n * Channel → accent colour. Unregistered channels fall through to gray.\n */\nexport const CHANNEL_COLORS: Record<string, string> = {\n // Shared diagnostics\n 'global-client': '#d2a8ff',\n\n // Section pins (desktop)\n 'every-channel-pin': '#9febd7',\n 'hero-pin': '#6ecc8b',\n 'pricing-pin': '#399587',\n 'product-screens-pin': '#4fafa0',\n 'social-proof-pin': '#ffbb8a',\n 'value-props-pin': '#e0a733',\n 'work-pin': '#f57e56',\n\n // Section pins (mobile)\n 'mobile-every-channel-pin': '#7ed9c6',\n 'mobile-hero-pin': '#f0eee6',\n 'mobile-pricing-pin': '#80d4ff',\n 'mobile-product-screens-pin': '#3a9085',\n 'mobile-social-proof-pin': '#ffd580',\n 'mobile-value-props-pin': '#4fafa0',\n};\n\nfunction flattenAttributes(input: Record<string, unknown>, prefix = ''): Record<string, string | number | boolean> {\n const output: Record<string, string | number | boolean> = {};\n\n for (const [key, value] of Object.entries(input)) {\n const nextKey = prefix ? `${prefix}.${key}` : key;\n if (value === null || value === undefined) continue;\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n output[nextKey] = value;\n continue;\n }\n\n if (Array.isArray(value)) {\n output[nextKey] = JSON.stringify(value);\n continue;\n }\n\n if (typeof value === 'object') {\n Object.assign(output, flattenAttributes(value as Record<string, unknown>, nextKey));\n continue;\n }\n\n output[nextKey] = String(value);\n }\n\n return output;\n}\n\nfunction stripTrailingSlash(host: string): string {\n return host.replace(/\\/+$/, '');\n}\n\nfunction enqueuePendingPostHogLog(entry: PendingShipLog): void {\n if (pendingPostHogLogs.length >= MAX_PENDING_POSTHOG_LOGS) {\n pendingPostHogLogs.shift();\n }\n pendingPostHogLogs.push(entry);\n}\n\nfunction flushPendingPostHogLogs(): void {\n if (!otelLogger || pendingPostHogLogs.length === 0) return;\n\n while (pendingPostHogLogs.length > 0) {\n const entry = pendingPostHogLogs.shift();\n if (!entry) break;\n emitToPostHog(entry.level, entry.channel, entry.event, entry.detail);\n }\n}\n\nexport function initializePostHogLogging(options: OTelInitOptions): void {\n if (typeof window === 'undefined') return;\n if (!options.apiKey?.trim()) return;\n\n const apiHost = stripTrailingSlash(options.apiHost?.trim() || 'https://us.i.posthog.com');\n const serviceName = options.serviceName?.trim() || 'keystone-customer-site';\n const environment = options.environment?.trim() || 'production';\n const fingerprint = `${apiHost}|${options.apiKey}|${serviceName}|${environment}|${options.accountId ?? ''}|${options.accountName ?? ''}`;\n if (otelLogger && otelInitFingerprint === fingerprint) return;\n\n if (otelProvider) {\n // Cleanly replace logger provider when config changes.\n void otelProvider.shutdown().catch(() => {});\n otelProvider = null;\n otelLogger = null;\n }\n\n const baseAttributes: Record<string, string | number | boolean> = {\n 'service.name': serviceName,\n environment,\n site_domain: window.location.hostname,\n };\n if (options.accountId !== undefined) baseAttributes.account_id = options.accountId;\n if (options.accountName) baseAttributes.account_name = options.accountName;\n\n const exporter = new OTLPLogExporter({\n url: `${apiHost}/i/v1/logs?token=${encodeURIComponent(options.apiKey)}`,\n headers: {\n // Keep request \"simple\" to avoid CORS preflight in browser.\n 'Content-Type': 'text/plain',\n },\n });\n\n otelProvider = new LoggerProvider({\n resource: resourceFromAttributes(baseAttributes),\n processors: [new BatchLogRecordProcessor(exporter)],\n });\n\n logs.setGlobalLoggerProvider(otelProvider);\n otelLogger = logs.getLogger(serviceName);\n otelInitFingerprint = fingerprint;\n flushPendingPostHogLogs();\n}\n\nfunction isConsoleEnabled(): boolean {\n if (BUILD_CONSOLE_DISABLED) return false;\n if (typeof window === 'undefined') return true;\n return (window as LoggingWindow).__loggingDisabled !== true;\n}\n\nfunction isPostHogShippingEnabled(): boolean {\n if (BUILD_POSTHOG_DISABLED) return false;\n if (typeof window === 'undefined') return false;\n return (window as LoggingWindow).__posthogLoggingDisabled !== true;\n}\n\nfunction formatDetail(detail: Record<string, unknown>): string {\n return Object.entries(detail)\n .map(([k, v]) => `${k}=${typeof v === 'number' ? v.toFixed(4) : String(v)}`)\n .join(' ');\n}\n\nfunction emitConsole(\n level: LogLevel,\n channel: string,\n event: string,\n detail: Record<string, unknown>,\n): void {\n const color = CHANNEL_COLORS[channel] ?? '#aaa';\n const detailStr = formatDetail(detail);\n const message = `%c[${channel}] %c${event}%c ${detailStr}`;\n const channelStyle = `color:${color}; font-weight:bold`;\n const eventStyle = level === 'error'\n ? 'color:#e94e4e; font-weight:bold'\n : level === 'warn'\n ? 'color:#f5a623; font-weight:bold'\n : 'color:#fff; font-weight:bold';\n const detailStyle = 'color:#999; font-weight:normal';\n\n if (level === 'error') {\n browserConsole?.error?.(message, channelStyle, eventStyle, detailStyle);\n return;\n }\n if (level === 'warn') {\n browserConsole?.warn?.(message, channelStyle, eventStyle, detailStyle);\n return;\n }\n browserConsole?.log?.(message, channelStyle, eventStyle, detailStyle);\n}\n\nfunction emitToPostHog(level: LogLevel, channel: string, event: string, detail: Record<string, unknown>): boolean {\n if (!otelLogger) return false;\n\n const severityText = level === 'warn' ? 'WARNING' : level === 'error' ? 'ERROR' : 'INFO';\n const attributes = flattenAttributes({ channel, ...detail });\n\n otelLogger.emit({\n severityText,\n body: event,\n attributes,\n });\n return true;\n}\n\nfunction emit(level: LogLevel, channel: string, event: string, detail: Record<string, unknown>, options?: LogOptions): void {\n const shouldShip = (options?.shipToPostHog ?? level !== 'info') && isPostHogShippingEnabled();\n // Keep warn/error visible even when regular logs are muted.\n if (level !== 'info' || isConsoleEnabled()) {\n emitConsole(level, channel, event, detail);\n }\n if (shouldShip) {\n const shipped = emitToPostHog(level, channel, event, detail);\n if (!shipped) {\n enqueuePendingPostHogLog({ level, channel, event, detail });\n }\n }\n}\n\nexport function log(channel: string, event: string, detail: Record<string, unknown> = {}, options?: LogOptions): void {\n emit('info', channel, event, detail, options);\n}\n\nexport function warn(channel: string, event: string, detail: Record<string, unknown> = {}, options?: LogOptions): void {\n emit('warn', channel, event, detail, options);\n}\n\nexport function error(channel: string, event: string, detail: Record<string, unknown> = {}, options?: LogOptions): void {\n emit('error', channel, event, detail, options);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -63,6 +63,127 @@ function getThemedComponent(componentName, theme = "classic") {
|
|
|
63
63
|
|
|
64
64
|
// src/contexts/ThemeContext.tsx
|
|
65
65
|
import { createContext, useContext } from "react";
|
|
66
|
+
|
|
67
|
+
// src/tracking/logging.ts
|
|
68
|
+
import { logs } from "@opentelemetry/api-logs";
|
|
69
|
+
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
70
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
71
|
+
import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
|
|
72
|
+
var BUILD_CONSOLE_DISABLED = process.env.NEXT_PUBLIC_LOGGING_DISABLED === "1";
|
|
73
|
+
var BUILD_POSTHOG_DISABLED = process.env.NEXT_PUBLIC_POSTHOG_LOGGING_DISABLED === "1";
|
|
74
|
+
var MAX_PENDING_POSTHOG_LOGS = 500;
|
|
75
|
+
var otelLogger = null;
|
|
76
|
+
var pendingPostHogLogs = [];
|
|
77
|
+
var browserConsole = globalThis == null ? void 0 : globalThis["console"];
|
|
78
|
+
var CHANNEL_COLORS = {
|
|
79
|
+
// Shared diagnostics
|
|
80
|
+
"global-client": "#d2a8ff",
|
|
81
|
+
// Section pins (desktop)
|
|
82
|
+
"every-channel-pin": "#9febd7",
|
|
83
|
+
"hero-pin": "#6ecc8b",
|
|
84
|
+
"pricing-pin": "#399587",
|
|
85
|
+
"product-screens-pin": "#4fafa0",
|
|
86
|
+
"social-proof-pin": "#ffbb8a",
|
|
87
|
+
"value-props-pin": "#e0a733",
|
|
88
|
+
"work-pin": "#f57e56",
|
|
89
|
+
// Section pins (mobile)
|
|
90
|
+
"mobile-every-channel-pin": "#7ed9c6",
|
|
91
|
+
"mobile-hero-pin": "#f0eee6",
|
|
92
|
+
"mobile-pricing-pin": "#80d4ff",
|
|
93
|
+
"mobile-product-screens-pin": "#3a9085",
|
|
94
|
+
"mobile-social-proof-pin": "#ffd580",
|
|
95
|
+
"mobile-value-props-pin": "#4fafa0"
|
|
96
|
+
};
|
|
97
|
+
function flattenAttributes(input, prefix = "") {
|
|
98
|
+
const output = {};
|
|
99
|
+
for (const [key, value] of Object.entries(input)) {
|
|
100
|
+
const nextKey = prefix ? `${prefix}.${key}` : key;
|
|
101
|
+
if (value === null || value === void 0) continue;
|
|
102
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
103
|
+
output[nextKey] = value;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
output[nextKey] = JSON.stringify(value);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (typeof value === "object") {
|
|
111
|
+
Object.assign(output, flattenAttributes(value, nextKey));
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
output[nextKey] = String(value);
|
|
115
|
+
}
|
|
116
|
+
return output;
|
|
117
|
+
}
|
|
118
|
+
function enqueuePendingPostHogLog(entry) {
|
|
119
|
+
if (pendingPostHogLogs.length >= MAX_PENDING_POSTHOG_LOGS) {
|
|
120
|
+
pendingPostHogLogs.shift();
|
|
121
|
+
}
|
|
122
|
+
pendingPostHogLogs.push(entry);
|
|
123
|
+
}
|
|
124
|
+
function isConsoleEnabled() {
|
|
125
|
+
if (BUILD_CONSOLE_DISABLED) return false;
|
|
126
|
+
if (typeof window === "undefined") return true;
|
|
127
|
+
return window.__loggingDisabled !== true;
|
|
128
|
+
}
|
|
129
|
+
function isPostHogShippingEnabled() {
|
|
130
|
+
if (BUILD_POSTHOG_DISABLED) return false;
|
|
131
|
+
if (typeof window === "undefined") return false;
|
|
132
|
+
return window.__posthogLoggingDisabled !== true;
|
|
133
|
+
}
|
|
134
|
+
function formatDetail(detail) {
|
|
135
|
+
return Object.entries(detail).map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : String(v)}`).join(" ");
|
|
136
|
+
}
|
|
137
|
+
function emitConsole(level, channel, event, detail) {
|
|
138
|
+
var _a, _b, _c, _d;
|
|
139
|
+
const color = (_a = CHANNEL_COLORS[channel]) != null ? _a : "#aaa";
|
|
140
|
+
const detailStr = formatDetail(detail);
|
|
141
|
+
const message = `%c[${channel}] %c${event}%c ${detailStr}`;
|
|
142
|
+
const channelStyle = `color:${color}; font-weight:bold`;
|
|
143
|
+
const eventStyle = level === "error" ? "color:#e94e4e; font-weight:bold" : level === "warn" ? "color:#f5a623; font-weight:bold" : "color:#fff; font-weight:bold";
|
|
144
|
+
const detailStyle = "color:#999; font-weight:normal";
|
|
145
|
+
if (level === "error") {
|
|
146
|
+
(_b = browserConsole == null ? void 0 : browserConsole.error) == null ? void 0 : _b.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (level === "warn") {
|
|
150
|
+
(_c = browserConsole == null ? void 0 : browserConsole.warn) == null ? void 0 : _c.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
(_d = browserConsole == null ? void 0 : browserConsole.log) == null ? void 0 : _d.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
|
|
154
|
+
}
|
|
155
|
+
function emitToPostHog(level, channel, event, detail) {
|
|
156
|
+
if (!otelLogger) return false;
|
|
157
|
+
const severityText = level === "warn" ? "WARNING" : level === "error" ? "ERROR" : "INFO";
|
|
158
|
+
const attributes = flattenAttributes(__spreadValues({ channel }, detail));
|
|
159
|
+
otelLogger.emit({
|
|
160
|
+
severityText,
|
|
161
|
+
body: event,
|
|
162
|
+
attributes
|
|
163
|
+
});
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
function emit(level, channel, event, detail, options) {
|
|
167
|
+
var _a;
|
|
168
|
+
const shouldShip = ((_a = options == null ? void 0 : options.shipToPostHog) != null ? _a : level !== "info") && isPostHogShippingEnabled();
|
|
169
|
+
if (level !== "info" || isConsoleEnabled()) {
|
|
170
|
+
emitConsole(level, channel, event, detail);
|
|
171
|
+
}
|
|
172
|
+
if (shouldShip) {
|
|
173
|
+
const shipped = emitToPostHog(level, channel, event, detail);
|
|
174
|
+
if (!shipped) {
|
|
175
|
+
enqueuePendingPostHogLog({ level, channel, event, detail });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function warn(channel, event, detail = {}, options) {
|
|
180
|
+
emit("warn", channel, event, detail, options);
|
|
181
|
+
}
|
|
182
|
+
function error(channel, event, detail = {}, options) {
|
|
183
|
+
emit("error", channel, event, detail, options);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/contexts/ThemeContext.tsx
|
|
66
187
|
var ThemeContext = createContext({ theme: "classic" });
|
|
67
188
|
function useTheme() {
|
|
68
189
|
return useContext(ThemeContext);
|
|
@@ -2399,7 +2520,9 @@ function GoogleMap({ address, locationName, className = "" }) {
|
|
|
2399
2520
|
return;
|
|
2400
2521
|
}
|
|
2401
2522
|
if (!window.google.maps.Geocoder) {
|
|
2402
|
-
|
|
2523
|
+
warn("google-map", "GEOCODER_NOT_READY_RETRYING", {
|
|
2524
|
+
address
|
|
2525
|
+
});
|
|
2403
2526
|
setTimeout(() => {
|
|
2404
2527
|
var _a, _b;
|
|
2405
2528
|
if (mapRef.current && ((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.Geocoder) && initMapRef.current) {
|
|
@@ -2457,8 +2580,12 @@ function GoogleMap({ address, locationName, className = "" }) {
|
|
|
2457
2580
|
}
|
|
2458
2581
|
isInitializingRef.current = false;
|
|
2459
2582
|
});
|
|
2460
|
-
} catch (
|
|
2461
|
-
|
|
2583
|
+
} catch (error2) {
|
|
2584
|
+
error("google-map", "MAP_INITIALIZATION_FAILED", {
|
|
2585
|
+
address,
|
|
2586
|
+
message: error2 instanceof Error ? error2.message : String(error2),
|
|
2587
|
+
stack: error2 instanceof Error ? error2.stack || "" : ""
|
|
2588
|
+
});
|
|
2462
2589
|
setMapError("Error loading map. Please try again later.");
|
|
2463
2590
|
isInitializingRef.current = false;
|
|
2464
2591
|
}
|