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/index.js CHANGED
@@ -81,6 +81,128 @@ function isValidTheme(theme) {
81
81
  return theme in THEME_CONFIG;
82
82
  }
83
83
 
84
+ // src/tracking/logging.ts
85
+ import { logs } from "@opentelemetry/api-logs";
86
+ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
87
+ import { resourceFromAttributes } from "@opentelemetry/resources";
88
+ import { BatchLogRecordProcessor, LoggerProvider } from "@opentelemetry/sdk-logs";
89
+ var BUILD_CONSOLE_DISABLED = process.env.NEXT_PUBLIC_LOGGING_DISABLED === "1";
90
+ var BUILD_POSTHOG_DISABLED = process.env.NEXT_PUBLIC_POSTHOG_LOGGING_DISABLED === "1";
91
+ var MAX_PENDING_POSTHOG_LOGS = 500;
92
+ var otelLogger = null;
93
+ var pendingPostHogLogs = [];
94
+ var browserConsole = globalThis == null ? void 0 : globalThis["console"];
95
+ var CHANNEL_COLORS = {
96
+ // Shared diagnostics
97
+ "global-client": "#d2a8ff",
98
+ // Section pins (desktop)
99
+ "every-channel-pin": "#9febd7",
100
+ "hero-pin": "#6ecc8b",
101
+ "pricing-pin": "#399587",
102
+ "product-screens-pin": "#4fafa0",
103
+ "social-proof-pin": "#ffbb8a",
104
+ "value-props-pin": "#e0a733",
105
+ "work-pin": "#f57e56",
106
+ // Section pins (mobile)
107
+ "mobile-every-channel-pin": "#7ed9c6",
108
+ "mobile-hero-pin": "#f0eee6",
109
+ "mobile-pricing-pin": "#80d4ff",
110
+ "mobile-product-screens-pin": "#3a9085",
111
+ "mobile-social-proof-pin": "#ffd580",
112
+ "mobile-value-props-pin": "#4fafa0"
113
+ };
114
+ function flattenAttributes(input, prefix = "") {
115
+ const output = {};
116
+ for (const [key, value] of Object.entries(input)) {
117
+ const nextKey = prefix ? `${prefix}.${key}` : key;
118
+ if (value === null || value === void 0) continue;
119
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
120
+ output[nextKey] = value;
121
+ continue;
122
+ }
123
+ if (Array.isArray(value)) {
124
+ output[nextKey] = JSON.stringify(value);
125
+ continue;
126
+ }
127
+ if (typeof value === "object") {
128
+ Object.assign(output, flattenAttributes(value, nextKey));
129
+ continue;
130
+ }
131
+ output[nextKey] = String(value);
132
+ }
133
+ return output;
134
+ }
135
+ function enqueuePendingPostHogLog(entry) {
136
+ if (pendingPostHogLogs.length >= MAX_PENDING_POSTHOG_LOGS) {
137
+ pendingPostHogLogs.shift();
138
+ }
139
+ pendingPostHogLogs.push(entry);
140
+ }
141
+ function isConsoleEnabled() {
142
+ if (BUILD_CONSOLE_DISABLED) return false;
143
+ if (typeof window === "undefined") return true;
144
+ return window.__loggingDisabled !== true;
145
+ }
146
+ function isPostHogShippingEnabled() {
147
+ if (BUILD_POSTHOG_DISABLED) return false;
148
+ if (typeof window === "undefined") return false;
149
+ return window.__posthogLoggingDisabled !== true;
150
+ }
151
+ function formatDetail(detail) {
152
+ return Object.entries(detail).map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : String(v)}`).join(" ");
153
+ }
154
+ function emitConsole(level, channel, event, detail) {
155
+ var _a, _b, _c, _d;
156
+ const color2 = (_a = CHANNEL_COLORS[channel]) != null ? _a : "#aaa";
157
+ const detailStr = formatDetail(detail);
158
+ const message = `%c[${channel}] %c${event}%c ${detailStr}`;
159
+ const channelStyle = `color:${color2}; font-weight:bold`;
160
+ const eventStyle = level === "error" ? "color:#e94e4e; font-weight:bold" : level === "warn" ? "color:#f5a623; font-weight:bold" : "color:#fff; font-weight:bold";
161
+ const detailStyle = "color:#999; font-weight:normal";
162
+ if (level === "error") {
163
+ (_b = browserConsole == null ? void 0 : browserConsole.error) == null ? void 0 : _b.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
164
+ return;
165
+ }
166
+ if (level === "warn") {
167
+ (_c = browserConsole == null ? void 0 : browserConsole.warn) == null ? void 0 : _c.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
168
+ return;
169
+ }
170
+ (_d = browserConsole == null ? void 0 : browserConsole.log) == null ? void 0 : _d.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
171
+ }
172
+ function emitToPostHog(level, channel, event, detail) {
173
+ if (!otelLogger) return false;
174
+ const severityText = level === "warn" ? "WARNING" : level === "error" ? "ERROR" : "INFO";
175
+ const attributes = flattenAttributes(__spreadValues({ channel }, detail));
176
+ otelLogger.emit({
177
+ severityText,
178
+ body: event,
179
+ attributes
180
+ });
181
+ return true;
182
+ }
183
+ function emit(level, channel, event, detail, options) {
184
+ var _a;
185
+ const shouldShip = ((_a = options == null ? void 0 : options.shipToPostHog) != null ? _a : level !== "info") && isPostHogShippingEnabled();
186
+ if (level !== "info" || isConsoleEnabled()) {
187
+ emitConsole(level, channel, event, detail);
188
+ }
189
+ if (shouldShip) {
190
+ const shipped = emitToPostHog(level, channel, event, detail);
191
+ if (!shipped) {
192
+ enqueuePendingPostHogLog({ level, channel, event, detail });
193
+ }
194
+ }
195
+ }
196
+ function log(channel, event, detail = {}, options) {
197
+ emit("info", channel, event, detail, options);
198
+ }
199
+ function warn(channel, event, detail = {}, options) {
200
+ emit("warn", channel, event, detail, options);
201
+ }
202
+ function error(channel, event, detail = {}, options) {
203
+ emit("error", channel, event, detail, options);
204
+ }
205
+
84
206
  // src/contexts/ThemeContext.tsx
85
207
  var ThemeContext = createContext({ theme: "classic" });
86
208
  function ThemeProvider({
@@ -88,7 +210,7 @@ function ThemeProvider({
88
210
  children
89
211
  }) {
90
212
  if (!isValidTheme(theme)) {
91
- console.warn(`Invalid theme "${theme}", falling back to "classic"`);
213
+ warn("theme", "INVALID_THEME_FALLBACK", { theme });
92
214
  theme = "classic";
93
215
  }
94
216
  return /* @__PURE__ */ React.createElement(ThemeContext.Provider, { value: { theme } }, children);
@@ -2435,7 +2557,9 @@ function GoogleMap({ address, locationName, className = "" }) {
2435
2557
  return;
2436
2558
  }
2437
2559
  if (!window.google.maps.Geocoder) {
2438
- console.warn("Google Maps Geocoder not yet available, retrying...");
2560
+ warn("google-map", "GEOCODER_NOT_READY_RETRYING", {
2561
+ address
2562
+ });
2439
2563
  setTimeout(() => {
2440
2564
  var _a, _b;
2441
2565
  if (mapRef.current && ((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.Geocoder) && initMapRef.current) {
@@ -2493,8 +2617,12 @@ function GoogleMap({ address, locationName, className = "" }) {
2493
2617
  }
2494
2618
  isInitializingRef.current = false;
2495
2619
  });
2496
- } catch (error) {
2497
- console.error("Error initializing map:", error);
2620
+ } catch (error2) {
2621
+ error("google-map", "MAP_INITIALIZATION_FAILED", {
2622
+ address,
2623
+ message: error2 instanceof Error ? error2.message : String(error2),
2624
+ stack: error2 instanceof Error ? error2.stack || "" : ""
2625
+ });
2498
2626
  setMapError("Error loading map. Please try again later.");
2499
2627
  isInitializingRef.current = false;
2500
2628
  }
@@ -6292,7 +6420,7 @@ async function setPixelUserData(userData) {
6292
6420
  function firePixelEvent(event, params, eventId) {
6293
6421
  const fbq = getFbq();
6294
6422
  if (!fbq) {
6295
- console.debug("[MetaPixel] skipped \u2014 fbq not loaded", { event });
6423
+ warn("meta-pixel", "PIXEL_EVENT_SKIPPED_FBQ_NOT_LOADED", { event });
6296
6424
  return;
6297
6425
  }
6298
6426
  applyStoredUserData(fbq);
@@ -6301,7 +6429,9 @@ function firePixelEvent(event, params, eventId) {
6301
6429
  if (params == null ? void 0 : params.contentCategory) normalized.content_category = params.contentCategory;
6302
6430
  const customData = Object.keys(normalized).length > 0 ? normalized : void 0;
6303
6431
  const eventData = eventId ? { eventID: eventId } : void 0;
6304
- console.debug("[MetaPixel]", event, normalized, eventId ? { eventID: eventId } : "");
6432
+ log("meta-pixel", "PIXEL_EVENT_FIRED", __spreadValues(__spreadValues({
6433
+ event
6434
+ }, normalized), eventId ? { eventId } : {}), { shipToPostHog: true });
6305
6435
  fbq("track", event, customData, eventData);
6306
6436
  }
6307
6437
 
@@ -7935,7 +8065,10 @@ var BlogPostSection = ({
7935
8065
  setCopied(true);
7936
8066
  setTimeout(() => setCopied(false), 2e3);
7937
8067
  } catch (err) {
7938
- console.error("Failed to copy:", err);
8068
+ error("blog-post", "COPY_LINK_FAILED", {
8069
+ message: err instanceof Error ? err.message : String(err),
8070
+ stack: err instanceof Error ? err.stack || "" : ""
8071
+ });
7939
8072
  }
7940
8073
  };
7941
8074
  const handleShareLink = () => {
@@ -7944,7 +8077,10 @@ var BlogPostSection = ({
7944
8077
  title: blogPost == null ? void 0 : blogPost.title,
7945
8078
  url: window.location.href
7946
8079
  }).catch((err) => {
7947
- console.error("Error sharing:", err);
8080
+ error("blog-post", "SHARE_LINK_FAILED", {
8081
+ message: err instanceof Error ? err.message : String(err),
8082
+ stack: err instanceof Error ? err.stack || "" : ""
8083
+ });
7948
8084
  });
7949
8085
  } else {
7950
8086
  handleCopyLink();
@@ -8007,7 +8143,10 @@ var BlogPostSection = ({
8007
8143
  onSubmit: (e) => {
8008
8144
  e.preventDefault();
8009
8145
  const formData = new FormData(e.currentTarget);
8010
- console.log("Form data:", formData);
8146
+ const email = formData.get("email");
8147
+ log("blog-post", "NEWSLETTER_FORM_SUBMIT", {
8148
+ email: typeof email === "string" ? email : ""
8149
+ }, { shipToPostHog: true });
8011
8150
  },
8012
8151
  className: "flex flex-col gap-4"
8013
8152
  },
@@ -8418,7 +8557,7 @@ var HomeHeroComponent = ({
8418
8557
  if (onEmailSubmit) {
8419
8558
  onEmailSubmit(email);
8420
8559
  } else {
8421
- console.log("Email signup:", email);
8560
+ log("home-hero", "EMAIL_SIGNUP_SUBMIT", { email }, { shipToPostHog: true });
8422
8561
  }
8423
8562
  },
8424
8563
  className: "mt-8 flex w-full flex-col items-stretch gap-4 md:mt-12 md:max-w-120 md:flex-row md:items-start"
@@ -19963,17 +20102,30 @@ function useRealtimeReplyOrchestrator({
19963
20102
  { channel: "ContactCommunicationsChannel", contact_id: String(contactIdForStream) },
19964
20103
  {
19965
20104
  connected: () => {
19966
- console.info(`[${debugLabel}] realtime connected contact_id=${contactIdForStream}`);
20105
+ log("chat-realtime", "REALTIME_CONNECTED", {
20106
+ debugLabel,
20107
+ contactId: contactIdForStream
20108
+ }, { shipToPostHog: true });
19967
20109
  },
19968
20110
  disconnected: () => {
19969
- console.warn(`[${debugLabel}] realtime disconnected contact_id=${contactIdForStream}`);
20111
+ warn("chat-realtime", "REALTIME_DISCONNECTED", {
20112
+ debugLabel,
20113
+ contactId: contactIdForStream
20114
+ });
19970
20115
  },
19971
20116
  rejected: () => {
19972
- console.warn(`[${debugLabel}] realtime rejected contact_id=${contactIdForStream}`);
20117
+ warn("chat-realtime", "REALTIME_REJECTED", {
20118
+ debugLabel,
20119
+ contactId: contactIdForStream
20120
+ });
19973
20121
  },
19974
20122
  received: async (data) => {
19975
20123
  var _a;
19976
- console.info(`[${debugLabel}] realtime received type=${(_a = data == null ? void 0 : data.type) != null ? _a : "unknown"} contact_id=${contactIdForStream}`);
20124
+ log("chat-realtime", "REALTIME_RECEIVED", {
20125
+ debugLabel,
20126
+ type: (_a = data == null ? void 0 : data.type) != null ? _a : "unknown",
20127
+ contactId: contactIdForStream
20128
+ }, { shipToPostHog: true });
19977
20129
  if ((data == null ? void 0 : data.type) === "agent_thinking") {
19978
20130
  onAgentThinking == null ? void 0 : onAgentThinking();
19979
20131
  return;
@@ -19984,8 +20136,13 @@ function useRealtimeReplyOrchestrator({
19984
20136
  if (hasReply) {
19985
20137
  resolveReply();
19986
20138
  }
19987
- } catch (error) {
19988
- console.error(`[${debugLabel}] realtime receive handling error`, error);
20139
+ } catch (error2) {
20140
+ error("chat-realtime", "REALTIME_RECEIVE_HANDLER_ERROR", {
20141
+ debugLabel,
20142
+ contactId: contactIdForStream,
20143
+ message: error2 instanceof Error ? error2.message : String(error2),
20144
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20145
+ });
19989
20146
  }
19990
20147
  }
19991
20148
  }
@@ -20072,8 +20229,11 @@ function ChatWidget({
20072
20229
  setMessages(newMessages);
20073
20230
  return newMessages;
20074
20231
  }
20075
- } catch (error) {
20076
- console.error("Failed to load messages:", error);
20232
+ } catch (error2) {
20233
+ error("chat-widget", "LOAD_MESSAGES_FAILED", {
20234
+ message: error2 instanceof Error ? error2.message : String(error2),
20235
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20236
+ });
20077
20237
  }
20078
20238
  return [];
20079
20239
  }, [contactId, sessionId]);
@@ -20168,14 +20328,17 @@ function ChatWidget({
20168
20328
  } else {
20169
20329
  setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
20170
20330
  captureEvent("chat_message_failed", { error: "send_failed" });
20171
- console.error("Failed to send message");
20331
+ error("chat-widget", "SEND_MESSAGE_NON_OK");
20172
20332
  setIsLoading(false);
20173
20333
  setWaitingForReply(false);
20174
20334
  }
20175
- } catch (error) {
20335
+ } catch (error2) {
20176
20336
  setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
20177
20337
  captureEvent("chat_message_failed", { error: "network_error" });
20178
- console.error("Failed to send message:", error);
20338
+ error("chat-widget", "SEND_MESSAGE_NETWORK_ERROR", {
20339
+ message: error2 instanceof Error ? error2.message : String(error2),
20340
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20341
+ });
20179
20342
  setIsLoading(false);
20180
20343
  setWaitingForReply(false);
20181
20344
  }