@farming-labs/theme 0.1.134 → 0.1.136
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,15 +1,105 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
//#region src/client-analytics.ts
|
|
4
|
+
const VISITOR_ID_STORAGE_KEY = "fd:analytics:visitor-id";
|
|
5
|
+
const SESSION_ID_STORAGE_KEY = "fd:analytics:session-id";
|
|
6
|
+
function createAnalyticsId(prefix) {
|
|
7
|
+
return `${prefix}_${typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 12)}`}`;
|
|
8
|
+
}
|
|
9
|
+
function readStorage(storage, key) {
|
|
10
|
+
try {
|
|
11
|
+
return storage?.getItem(key)?.trim() || void 0;
|
|
12
|
+
} catch {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function writeStorage(storage, key, value) {
|
|
17
|
+
try {
|
|
18
|
+
storage?.setItem(key, value);
|
|
19
|
+
} catch {}
|
|
20
|
+
}
|
|
21
|
+
function getBrowserStorage(target, key) {
|
|
22
|
+
try {
|
|
23
|
+
return target[key];
|
|
24
|
+
} catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function getOrCreateClientId({ cachedValue, create, storage, storageKey }) {
|
|
29
|
+
const stored = readStorage(storage, storageKey);
|
|
30
|
+
const value = stored ?? cachedValue ?? create();
|
|
31
|
+
if (!stored) writeStorage(storage, storageKey, value);
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
function getDocsClientAnalyticsIdentity() {
|
|
35
|
+
if (typeof window === "undefined") return null;
|
|
36
|
+
const target = window;
|
|
37
|
+
const visitorId = getOrCreateClientId({
|
|
38
|
+
cachedValue: target.__fdAnalyticsVisitorId__,
|
|
39
|
+
create: () => createAnalyticsId("visitor"),
|
|
40
|
+
storage: getBrowserStorage(target, "localStorage"),
|
|
41
|
+
storageKey: VISITOR_ID_STORAGE_KEY
|
|
42
|
+
});
|
|
43
|
+
const sessionId = getOrCreateClientId({
|
|
44
|
+
cachedValue: target.__fdAnalyticsSessionId__,
|
|
45
|
+
create: () => createAnalyticsId("session"),
|
|
46
|
+
storage: getBrowserStorage(target, "sessionStorage"),
|
|
47
|
+
storageKey: SESSION_ID_STORAGE_KEY
|
|
48
|
+
});
|
|
49
|
+
target.__fdAnalyticsVisitorId__ = visitorId;
|
|
50
|
+
target.__fdAnalyticsSessionId__ = sessionId;
|
|
51
|
+
return {
|
|
52
|
+
anonymousId: visitorId,
|
|
53
|
+
visitorId,
|
|
54
|
+
sessionId,
|
|
55
|
+
visitor: { id: visitorId },
|
|
56
|
+
session: { id: sessionId }
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function asRecord(value) {
|
|
60
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
61
|
+
}
|
|
62
|
+
function asString(value) {
|
|
63
|
+
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
64
|
+
}
|
|
65
|
+
function normalizeClientAnalyticsProperties(identity, properties) {
|
|
66
|
+
const provided = properties ?? {};
|
|
67
|
+
const visitorId = asString(provided.visitorId) ?? asString(asRecord(provided.visitor).id) ?? asString(provided.anonymousId) ?? identity?.visitorId;
|
|
68
|
+
const sessionId = asString(provided.sessionId) ?? asString(asRecord(provided.session).id) ?? identity?.sessionId;
|
|
69
|
+
const merged = {
|
|
70
|
+
...identity ?? {},
|
|
71
|
+
...provided
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
...merged,
|
|
75
|
+
...visitorId ? {
|
|
76
|
+
anonymousId: asString(provided.anonymousId) ?? visitorId,
|
|
77
|
+
visitorId,
|
|
78
|
+
visitor: {
|
|
79
|
+
...asRecord(merged.visitor),
|
|
80
|
+
id: visitorId
|
|
81
|
+
}
|
|
82
|
+
} : {},
|
|
83
|
+
...sessionId ? {
|
|
84
|
+
sessionId,
|
|
85
|
+
session: {
|
|
86
|
+
...asRecord(merged.session),
|
|
87
|
+
id: sessionId
|
|
88
|
+
}
|
|
89
|
+
} : {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
4
92
|
function emitClientAnalyticsEvent(event) {
|
|
5
93
|
if (typeof window === "undefined") return;
|
|
94
|
+
const identity = getDocsClientAnalyticsIdentity();
|
|
6
95
|
const normalized = {
|
|
7
96
|
...event,
|
|
8
97
|
source: "client",
|
|
9
|
-
path: window.location.pathname,
|
|
10
|
-
url: window.location.href,
|
|
11
|
-
referrer: document.referrer || void 0,
|
|
12
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
98
|
+
path: event.path ?? window.location.pathname,
|
|
99
|
+
url: event.url ?? window.location.href,
|
|
100
|
+
referrer: event.referrer ?? (document.referrer || void 0),
|
|
101
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
102
|
+
properties: normalizeClientAnalyticsProperties(identity, event.properties)
|
|
13
103
|
};
|
|
14
104
|
const target = window;
|
|
15
105
|
try {
|
|
@@ -5,6 +5,7 @@ type CopyHandler = (data: CodeBlockCopyData) => void;
|
|
|
5
5
|
type FeedbackHandler = (data: DocsFeedbackData) => void | Promise<void>;
|
|
6
6
|
type AIActionHandler = (data: DocsAskAIActionData) => void | Promise<void>;
|
|
7
7
|
type AIFeedbackHandler = (data: DocsAskAIFeedbackData) => void | Promise<void>;
|
|
8
|
+
declare function isDocsClientAnalyticsEnabled(analytics?: boolean | DocsAnalyticsConfig): boolean;
|
|
8
9
|
declare function DocsClientHooks({
|
|
9
10
|
onCopyClick,
|
|
10
11
|
onFeedback,
|
|
@@ -19,4 +20,4 @@ declare function DocsClientHooks({
|
|
|
19
20
|
analytics?: boolean | DocsAnalyticsConfig;
|
|
20
21
|
}): null;
|
|
21
22
|
//#endregion
|
|
22
|
-
export { DocsClientHooks };
|
|
23
|
+
export { DocsClientHooks, isDocsClientAnalyticsEnabled };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { emitClientAnalyticsEvent } from "./client-analytics.mjs";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
|
-
import { emitDocsAnalyticsEvent } from "@farming-labs/docs";
|
|
5
|
+
import { emitDocsAnalyticsEvent, resolveDocsAnalyticsConfig } from "@farming-labs/docs";
|
|
6
6
|
|
|
7
7
|
//#region src/docs-client-hooks.tsx
|
|
8
8
|
function useWindowHook(key, handler) {
|
|
@@ -18,10 +18,13 @@ function useWindowHook(key, handler) {
|
|
|
18
18
|
};
|
|
19
19
|
}, [handler, key]);
|
|
20
20
|
}
|
|
21
|
+
function isDocsClientAnalyticsEnabled(analytics) {
|
|
22
|
+
return resolveDocsAnalyticsConfig(analytics).enabled;
|
|
23
|
+
}
|
|
21
24
|
function useAnalyticsHook(analytics) {
|
|
22
25
|
useEffect(() => {
|
|
23
26
|
if (typeof window === "undefined") return;
|
|
24
|
-
if (!analytics) return;
|
|
27
|
+
if (!isDocsClientAnalyticsEnabled(analytics)) return;
|
|
25
28
|
const target = window;
|
|
26
29
|
const handler = (event) => {
|
|
27
30
|
emitDocsAnalyticsEvent(analytics, event);
|
|
@@ -40,7 +43,7 @@ function useAnalyticsHook(analytics) {
|
|
|
40
43
|
function useCodeCopyAnalytics(analytics) {
|
|
41
44
|
useEffect(() => {
|
|
42
45
|
if (typeof window === "undefined") return;
|
|
43
|
-
if (!analytics) return;
|
|
46
|
+
if (!isDocsClientAnalyticsEnabled(analytics)) return;
|
|
44
47
|
const handleClick = (event) => {
|
|
45
48
|
const target = event.target;
|
|
46
49
|
if (!target.closest?.("button")) return;
|
|
@@ -76,4 +79,4 @@ function DocsClientHooks({ onCopyClick, onFeedback, onAIActions, onAIFeedback, a
|
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
//#endregion
|
|
79
|
-
export { DocsClientHooks };
|
|
82
|
+
export { DocsClientHooks, isDocsClientAnalyticsEnabled };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { CommandGridUIDefaults, commandGrid } from "./command-grid/index.mjs";
|
|
2
2
|
import { ConcreteUIDefaults, concrete } from "./concrete/index.mjs";
|
|
3
3
|
import { DefaultUIDefaults, fumadocs } from "./default/index.mjs";
|
|
4
|
+
import { DocsClientHooks } from "./docs-client-hooks.mjs";
|
|
4
5
|
import { DocsCommandSearch } from "./docs-command-search.mjs";
|
|
5
6
|
import { createDocsLayout, createDocsMetadata, createPageMetadata } from "./docs-layout.mjs";
|
|
6
7
|
import { DocsPageClient } from "./docs-page-client.mjs";
|
|
7
8
|
import { HardlineUIDefaults, hardline } from "./hardline/index.mjs";
|
|
8
9
|
import { RootProvider } from "./provider.mjs";
|
|
9
10
|
import { LedgerUIDefaults, ledger } from "./ledger/index.mjs";
|
|
10
|
-
import { DocsClientHooks } from "./docs-client-hooks.mjs";
|
|
11
11
|
import { DocsFeedback, DocsFeedbackProps } from "./docs-feedback.mjs";
|
|
12
12
|
import { PageActions } from "./page-actions.mjs";
|
|
13
13
|
import { withLangInUrl } from "./i18n.mjs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.136",
|
|
4
4
|
"description": "Theme package for @farming-labs/docs — layout, provider, MDX components, and styles",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"tsdown": "^0.20.3",
|
|
140
140
|
"typescript": "^5.9.3",
|
|
141
141
|
"vitest": "^3.2.4",
|
|
142
|
-
"@farming-labs/docs": "0.1.
|
|
142
|
+
"@farming-labs/docs": "0.1.136"
|
|
143
143
|
},
|
|
144
144
|
"peerDependencies": {
|
|
145
145
|
"@farming-labs/docs": ">=0.0.1",
|