keystone-design-bootstrap 1.0.97 → 1.0.98

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,116 @@ 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 otelLogger = null;
92
+ var browserConsole = globalThis == null ? void 0 : globalThis["console"];
93
+ var CHANNEL_COLORS = {
94
+ // Shared diagnostics
95
+ "global-client": "#d2a8ff",
96
+ // Section pins (desktop)
97
+ "every-channel-pin": "#9febd7",
98
+ "hero-pin": "#6ecc8b",
99
+ "pricing-pin": "#399587",
100
+ "product-screens-pin": "#4fafa0",
101
+ "social-proof-pin": "#ffbb8a",
102
+ "value-props-pin": "#e0a733",
103
+ "work-pin": "#f57e56",
104
+ // Section pins (mobile)
105
+ "mobile-every-channel-pin": "#7ed9c6",
106
+ "mobile-hero-pin": "#f0eee6",
107
+ "mobile-pricing-pin": "#80d4ff",
108
+ "mobile-product-screens-pin": "#3a9085",
109
+ "mobile-social-proof-pin": "#ffd580",
110
+ "mobile-value-props-pin": "#4fafa0"
111
+ };
112
+ function flattenAttributes(input, prefix = "") {
113
+ const output = {};
114
+ for (const [key, value] of Object.entries(input)) {
115
+ const nextKey = prefix ? `${prefix}.${key}` : key;
116
+ if (value === null || value === void 0) continue;
117
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
118
+ output[nextKey] = value;
119
+ continue;
120
+ }
121
+ if (Array.isArray(value)) {
122
+ output[nextKey] = JSON.stringify(value);
123
+ continue;
124
+ }
125
+ if (typeof value === "object") {
126
+ Object.assign(output, flattenAttributes(value, nextKey));
127
+ continue;
128
+ }
129
+ output[nextKey] = String(value);
130
+ }
131
+ return output;
132
+ }
133
+ function isConsoleEnabled() {
134
+ if (BUILD_CONSOLE_DISABLED) return false;
135
+ if (typeof window === "undefined") return true;
136
+ return window.__loggingDisabled !== true;
137
+ }
138
+ function isPostHogShippingEnabled() {
139
+ if (BUILD_POSTHOG_DISABLED) return false;
140
+ if (typeof window === "undefined") return false;
141
+ return window.__posthogLoggingDisabled !== true;
142
+ }
143
+ function formatDetail(detail) {
144
+ return Object.entries(detail).map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(4) : String(v)}`).join(" ");
145
+ }
146
+ function emitConsole(level, channel, event, detail) {
147
+ var _a, _b, _c, _d;
148
+ const color2 = (_a = CHANNEL_COLORS[channel]) != null ? _a : "#aaa";
149
+ const detailStr = formatDetail(detail);
150
+ const message = `%c[${channel}] %c${event}%c ${detailStr}`;
151
+ const channelStyle = `color:${color2}; font-weight:bold`;
152
+ const eventStyle = level === "error" ? "color:#e94e4e; font-weight:bold" : level === "warn" ? "color:#f5a623; font-weight:bold" : "color:#fff; font-weight:bold";
153
+ const detailStyle = "color:#999; font-weight:normal";
154
+ if (level === "error") {
155
+ (_b = browserConsole == null ? void 0 : browserConsole.error) == null ? void 0 : _b.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
156
+ return;
157
+ }
158
+ if (level === "warn") {
159
+ (_c = browserConsole == null ? void 0 : browserConsole.warn) == null ? void 0 : _c.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
160
+ return;
161
+ }
162
+ (_d = browserConsole == null ? void 0 : browserConsole.log) == null ? void 0 : _d.call(browserConsole, message, channelStyle, eventStyle, detailStyle);
163
+ }
164
+ function emitToPostHog(level, channel, event, detail) {
165
+ if (!otelLogger) return;
166
+ const severityText = level === "warn" ? "WARNING" : level === "error" ? "ERROR" : "INFO";
167
+ const attributes = flattenAttributes(__spreadValues({ channel }, detail));
168
+ otelLogger.emit({
169
+ severityText,
170
+ body: event,
171
+ attributes
172
+ });
173
+ }
174
+ function emit(level, channel, event, detail, options) {
175
+ var _a;
176
+ const shouldShip = ((_a = options == null ? void 0 : options.shipToPostHog) != null ? _a : level !== "info") && isPostHogShippingEnabled();
177
+ if (level !== "info" || isConsoleEnabled()) {
178
+ emitConsole(level, channel, event, detail);
179
+ }
180
+ if (shouldShip) {
181
+ emitToPostHog(level, channel, event, detail);
182
+ }
183
+ }
184
+ function log(channel, event, detail = {}, options) {
185
+ emit("info", channel, event, detail, options);
186
+ }
187
+ function warn(channel, event, detail = {}, options) {
188
+ emit("warn", channel, event, detail, options);
189
+ }
190
+ function error(channel, event, detail = {}, options) {
191
+ emit("error", channel, event, detail, options);
192
+ }
193
+
84
194
  // src/contexts/ThemeContext.tsx
85
195
  var ThemeContext = createContext({ theme: "classic" });
86
196
  function ThemeProvider({
@@ -88,7 +198,7 @@ function ThemeProvider({
88
198
  children
89
199
  }) {
90
200
  if (!isValidTheme(theme)) {
91
- console.warn(`Invalid theme "${theme}", falling back to "classic"`);
201
+ warn("theme", "INVALID_THEME_FALLBACK", { theme });
92
202
  theme = "classic";
93
203
  }
94
204
  return /* @__PURE__ */ React.createElement(ThemeContext.Provider, { value: { theme } }, children);
@@ -2435,7 +2545,9 @@ function GoogleMap({ address, locationName, className = "" }) {
2435
2545
  return;
2436
2546
  }
2437
2547
  if (!window.google.maps.Geocoder) {
2438
- console.warn("Google Maps Geocoder not yet available, retrying...");
2548
+ warn("google-map", "GEOCODER_NOT_READY_RETRYING", {
2549
+ address
2550
+ });
2439
2551
  setTimeout(() => {
2440
2552
  var _a, _b;
2441
2553
  if (mapRef.current && ((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.Geocoder) && initMapRef.current) {
@@ -2493,8 +2605,12 @@ function GoogleMap({ address, locationName, className = "" }) {
2493
2605
  }
2494
2606
  isInitializingRef.current = false;
2495
2607
  });
2496
- } catch (error) {
2497
- console.error("Error initializing map:", error);
2608
+ } catch (error2) {
2609
+ error("google-map", "MAP_INITIALIZATION_FAILED", {
2610
+ address,
2611
+ message: error2 instanceof Error ? error2.message : String(error2),
2612
+ stack: error2 instanceof Error ? error2.stack || "" : ""
2613
+ });
2498
2614
  setMapError("Error loading map. Please try again later.");
2499
2615
  isInitializingRef.current = false;
2500
2616
  }
@@ -6292,7 +6408,7 @@ async function setPixelUserData(userData) {
6292
6408
  function firePixelEvent(event, params, eventId) {
6293
6409
  const fbq = getFbq();
6294
6410
  if (!fbq) {
6295
- console.debug("[MetaPixel] skipped \u2014 fbq not loaded", { event });
6411
+ warn("meta-pixel", "PIXEL_EVENT_SKIPPED_FBQ_NOT_LOADED", { event });
6296
6412
  return;
6297
6413
  }
6298
6414
  applyStoredUserData(fbq);
@@ -6301,7 +6417,9 @@ function firePixelEvent(event, params, eventId) {
6301
6417
  if (params == null ? void 0 : params.contentCategory) normalized.content_category = params.contentCategory;
6302
6418
  const customData = Object.keys(normalized).length > 0 ? normalized : void 0;
6303
6419
  const eventData = eventId ? { eventID: eventId } : void 0;
6304
- console.debug("[MetaPixel]", event, normalized, eventId ? { eventID: eventId } : "");
6420
+ log("meta-pixel", "PIXEL_EVENT_FIRED", __spreadValues(__spreadValues({
6421
+ event
6422
+ }, normalized), eventId ? { eventId } : {}), { shipToPostHog: true });
6305
6423
  fbq("track", event, customData, eventData);
6306
6424
  }
6307
6425
 
@@ -7935,7 +8053,10 @@ var BlogPostSection = ({
7935
8053
  setCopied(true);
7936
8054
  setTimeout(() => setCopied(false), 2e3);
7937
8055
  } catch (err) {
7938
- console.error("Failed to copy:", err);
8056
+ error("blog-post", "COPY_LINK_FAILED", {
8057
+ message: err instanceof Error ? err.message : String(err),
8058
+ stack: err instanceof Error ? err.stack || "" : ""
8059
+ });
7939
8060
  }
7940
8061
  };
7941
8062
  const handleShareLink = () => {
@@ -7944,7 +8065,10 @@ var BlogPostSection = ({
7944
8065
  title: blogPost == null ? void 0 : blogPost.title,
7945
8066
  url: window.location.href
7946
8067
  }).catch((err) => {
7947
- console.error("Error sharing:", err);
8068
+ error("blog-post", "SHARE_LINK_FAILED", {
8069
+ message: err instanceof Error ? err.message : String(err),
8070
+ stack: err instanceof Error ? err.stack || "" : ""
8071
+ });
7948
8072
  });
7949
8073
  } else {
7950
8074
  handleCopyLink();
@@ -8007,7 +8131,10 @@ var BlogPostSection = ({
8007
8131
  onSubmit: (e) => {
8008
8132
  e.preventDefault();
8009
8133
  const formData = new FormData(e.currentTarget);
8010
- console.log("Form data:", formData);
8134
+ const email = formData.get("email");
8135
+ log("blog-post", "NEWSLETTER_FORM_SUBMIT", {
8136
+ email: typeof email === "string" ? email : ""
8137
+ }, { shipToPostHog: true });
8011
8138
  },
8012
8139
  className: "flex flex-col gap-4"
8013
8140
  },
@@ -8418,7 +8545,7 @@ var HomeHeroComponent = ({
8418
8545
  if (onEmailSubmit) {
8419
8546
  onEmailSubmit(email);
8420
8547
  } else {
8421
- console.log("Email signup:", email);
8548
+ log("home-hero", "EMAIL_SIGNUP_SUBMIT", { email }, { shipToPostHog: true });
8422
8549
  }
8423
8550
  },
8424
8551
  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 +20090,30 @@ function useRealtimeReplyOrchestrator({
19963
20090
  { channel: "ContactCommunicationsChannel", contact_id: String(contactIdForStream) },
19964
20091
  {
19965
20092
  connected: () => {
19966
- console.info(`[${debugLabel}] realtime connected contact_id=${contactIdForStream}`);
20093
+ log("chat-realtime", "REALTIME_CONNECTED", {
20094
+ debugLabel,
20095
+ contactId: contactIdForStream
20096
+ }, { shipToPostHog: true });
19967
20097
  },
19968
20098
  disconnected: () => {
19969
- console.warn(`[${debugLabel}] realtime disconnected contact_id=${contactIdForStream}`);
20099
+ warn("chat-realtime", "REALTIME_DISCONNECTED", {
20100
+ debugLabel,
20101
+ contactId: contactIdForStream
20102
+ });
19970
20103
  },
19971
20104
  rejected: () => {
19972
- console.warn(`[${debugLabel}] realtime rejected contact_id=${contactIdForStream}`);
20105
+ warn("chat-realtime", "REALTIME_REJECTED", {
20106
+ debugLabel,
20107
+ contactId: contactIdForStream
20108
+ });
19973
20109
  },
19974
20110
  received: async (data) => {
19975
20111
  var _a;
19976
- console.info(`[${debugLabel}] realtime received type=${(_a = data == null ? void 0 : data.type) != null ? _a : "unknown"} contact_id=${contactIdForStream}`);
20112
+ log("chat-realtime", "REALTIME_RECEIVED", {
20113
+ debugLabel,
20114
+ type: (_a = data == null ? void 0 : data.type) != null ? _a : "unknown",
20115
+ contactId: contactIdForStream
20116
+ }, { shipToPostHog: true });
19977
20117
  if ((data == null ? void 0 : data.type) === "agent_thinking") {
19978
20118
  onAgentThinking == null ? void 0 : onAgentThinking();
19979
20119
  return;
@@ -19984,8 +20124,13 @@ function useRealtimeReplyOrchestrator({
19984
20124
  if (hasReply) {
19985
20125
  resolveReply();
19986
20126
  }
19987
- } catch (error) {
19988
- console.error(`[${debugLabel}] realtime receive handling error`, error);
20127
+ } catch (error2) {
20128
+ error("chat-realtime", "REALTIME_RECEIVE_HANDLER_ERROR", {
20129
+ debugLabel,
20130
+ contactId: contactIdForStream,
20131
+ message: error2 instanceof Error ? error2.message : String(error2),
20132
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20133
+ });
19989
20134
  }
19990
20135
  }
19991
20136
  }
@@ -20072,8 +20217,11 @@ function ChatWidget({
20072
20217
  setMessages(newMessages);
20073
20218
  return newMessages;
20074
20219
  }
20075
- } catch (error) {
20076
- console.error("Failed to load messages:", error);
20220
+ } catch (error2) {
20221
+ error("chat-widget", "LOAD_MESSAGES_FAILED", {
20222
+ message: error2 instanceof Error ? error2.message : String(error2),
20223
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20224
+ });
20077
20225
  }
20078
20226
  return [];
20079
20227
  }, [contactId, sessionId]);
@@ -20168,14 +20316,17 @@ function ChatWidget({
20168
20316
  } else {
20169
20317
  setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
20170
20318
  captureEvent("chat_message_failed", { error: "send_failed" });
20171
- console.error("Failed to send message");
20319
+ error("chat-widget", "SEND_MESSAGE_NON_OK");
20172
20320
  setIsLoading(false);
20173
20321
  setWaitingForReply(false);
20174
20322
  }
20175
- } catch (error) {
20323
+ } catch (error2) {
20176
20324
  setMessages((prev) => prev.filter((m) => m.id !== tempMessage.id));
20177
20325
  captureEvent("chat_message_failed", { error: "network_error" });
20178
- console.error("Failed to send message:", error);
20326
+ error("chat-widget", "SEND_MESSAGE_NETWORK_ERROR", {
20327
+ message: error2 instanceof Error ? error2.message : String(error2),
20328
+ stack: error2 instanceof Error ? error2.stack || "" : ""
20329
+ });
20179
20330
  setIsLoading(false);
20180
20331
  setWaitingForReply(false);
20181
20332
  }