@farming-labs/theme 0.1.60 → 0.1.63

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.
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import { emitClientAnalyticsEvent } from "./client-analytics.mjs";
3
4
  import { useWindowSearchParams } from "./client-location.mjs";
4
5
  import { resolveClientLocale, withLangInUrl } from "./i18n.mjs";
5
6
  import { AIModalDialog, DocsSearchDialog, FloatingAIChat } from "./ai-search-dialog.mjs";
@@ -21,7 +22,7 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
21
22
  * This component is rendered inside the docs layout so the user's root layout
22
23
  * never needs to be modified — AI features work purely from `docs.config.ts`.
23
24
  */
24
- function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-right", floatingStyle = "panel", triggerComponentHtml, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId }) {
25
+ function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-right", floatingStyle = "panel", triggerComponentHtml, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId, analytics = false }) {
25
26
  const localizedApi = withLangInUrl(api, resolveClientLocale(useWindowSearchParams(), locale));
26
27
  if (mode === "search") return /* @__PURE__ */ jsx(SearchModeAI, {
27
28
  api: localizedApi,
@@ -30,7 +31,8 @@ function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-ri
30
31
  loaderVariant,
31
32
  loadingComponentHtml,
32
33
  models,
33
- defaultModelId
34
+ defaultModelId,
35
+ analytics
34
36
  });
35
37
  if (mode === "sidebar-icon") return /* @__PURE__ */ jsx(SidebarIconModeAI, {
36
38
  api: localizedApi,
@@ -39,7 +41,8 @@ function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-ri
39
41
  loaderVariant,
40
42
  loadingComponentHtml,
41
43
  models,
42
- defaultModelId
44
+ defaultModelId,
45
+ analytics
43
46
  });
44
47
  return /* @__PURE__ */ jsx(FloatingAIChat, {
45
48
  api: localizedApi,
@@ -51,10 +54,11 @@ function DocsAIFeatures({ mode, api = "/api/docs", locale, position = "bottom-ri
51
54
  loaderVariant,
52
55
  loadingComponentHtml,
53
56
  models,
54
- defaultModelId
57
+ defaultModelId,
58
+ analytics
55
59
  });
56
60
  }
57
- function SearchModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId }) {
61
+ function SearchModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId, analytics }) {
58
62
  const [open, setOpen] = useState(false);
59
63
  useEffect(() => {
60
64
  function handler(e) {
@@ -63,11 +67,18 @@ function SearchModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loading
63
67
  e.stopPropagation();
64
68
  e.stopImmediatePropagation();
65
69
  setOpen(true);
70
+ if (analytics) emitClientAnalyticsEvent({
71
+ type: "search_open",
72
+ properties: {
73
+ mode: "ai-search",
74
+ trigger: "keyboard"
75
+ }
76
+ });
66
77
  }
67
78
  }
68
79
  document.addEventListener("keydown", handler, true);
69
80
  return () => document.removeEventListener("keydown", handler, true);
70
- }, []);
81
+ }, [analytics]);
71
82
  useEffect(() => {
72
83
  function handler(e) {
73
84
  const button = e.target.closest("button");
@@ -78,11 +89,18 @@ function SearchModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loading
78
89
  e.stopPropagation();
79
90
  e.stopImmediatePropagation();
80
91
  setOpen(true);
92
+ if (analytics) emitClientAnalyticsEvent({
93
+ type: "search_open",
94
+ properties: {
95
+ mode: "ai-search",
96
+ trigger: "button"
97
+ }
98
+ });
81
99
  }
82
100
  }
83
101
  document.addEventListener("click", handler, true);
84
102
  return () => document.removeEventListener("click", handler, true);
85
- }, []);
103
+ }, [analytics]);
86
104
  return /* @__PURE__ */ jsx(DocsSearchDialog, {
87
105
  open,
88
106
  onOpenChange: setOpen,
@@ -92,10 +110,11 @@ function SearchModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loading
92
110
  loaderVariant,
93
111
  loadingComponentHtml,
94
112
  models,
95
- defaultModelId
113
+ defaultModelId,
114
+ analytics
96
115
  });
97
116
  }
98
- function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId }) {
117
+ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, loadingComponentHtml, models, defaultModelId, analytics }) {
99
118
  const [searchOpen, setSearchOpen] = useState(false);
100
119
  const [aiOpen, setAiOpen] = useState(false);
101
120
  useEffect(() => {
@@ -113,9 +132,23 @@ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, lo
113
132
  useEffect(() => {
114
133
  function onSearch() {
115
134
  setSearchOpen(true);
135
+ if (analytics) emitClientAnalyticsEvent({
136
+ type: "search_open",
137
+ properties: {
138
+ mode: "sidebar-icon",
139
+ trigger: "sidebar-search"
140
+ }
141
+ });
116
142
  }
117
143
  function onAI() {
118
144
  setAiOpen(true);
145
+ if (analytics) emitClientAnalyticsEvent({
146
+ type: "ai_open",
147
+ properties: {
148
+ mode: "sidebar-icon",
149
+ trigger: "sidebar-ai"
150
+ }
151
+ });
119
152
  }
120
153
  window.addEventListener("fd-open-search", onSearch);
121
154
  window.addEventListener("fd-open-ai", onAI);
@@ -123,7 +156,7 @@ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, lo
123
156
  window.removeEventListener("fd-open-search", onSearch);
124
157
  window.removeEventListener("fd-open-ai", onAI);
125
158
  };
126
- }, []);
159
+ }, [analytics]);
127
160
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DocsSearchDialog, {
128
161
  open: searchOpen,
129
162
  onOpenChange: setSearchOpen,
@@ -133,7 +166,8 @@ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, lo
133
166
  loaderVariant,
134
167
  loadingComponentHtml,
135
168
  models,
136
- defaultModelId
169
+ defaultModelId,
170
+ analytics
137
171
  }), /* @__PURE__ */ jsx(AIModalDialog, {
138
172
  open: aiOpen,
139
173
  onOpenChange: setAiOpen,
@@ -143,7 +177,8 @@ function SidebarIconModeAI({ api, suggestedQuestions, aiLabel, loaderVariant, lo
143
177
  loaderVariant,
144
178
  loadingComponentHtml,
145
179
  models,
146
- defaultModelId
180
+ defaultModelId,
181
+ analytics
147
182
  })] });
148
183
  }
149
184
 
@@ -1,4 +1,4 @@
1
- import { ChangelogConfig, DocsI18nConfig, DocsMcpConfig, DocsSearchConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
1
+ import { ChangelogConfig, DocsAnalyticsConfig, DocsI18nConfig, DocsMcpConfig, DocsSearchConfig, FeedbackConfig, OrderingItem } from "@farming-labs/docs";
2
2
 
3
3
  //#region src/docs-api.d.ts
4
4
  interface AIProviderConfig {
@@ -41,6 +41,8 @@ interface DocsAPIOptions {
41
41
  i18n?: DocsI18nConfig;
42
42
  /** Search configuration */
43
43
  search?: boolean | DocsSearchConfig;
44
+ /** Analytics configuration */
45
+ analytics?: boolean | DocsAnalyticsConfig;
44
46
  /** Feedback configuration */
45
47
  feedback?: boolean | FeedbackConfig;
46
48
  /** MCP configuration used for the agent discovery spec. */
@@ -56,6 +58,7 @@ interface DocsMCPAPIOptions {
56
58
  ordering?: "alphabetical" | "numeric" | OrderingItem[];
57
59
  mcp?: boolean | DocsMcpConfig;
58
60
  search?: boolean | DocsSearchConfig;
61
+ analytics?: boolean | DocsAnalyticsConfig;
59
62
  }
60
63
  /**
61
64
  * Create a unified docs API route handler.