kansoku-react 0.0.0-stage → 0.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,17 @@
1
+ # kansoku-react
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b1c1458: Initial browser SDK: page views with navigation and attribution capture, session
8
+ and identity helpers (including set-once traits and keyed email), experiment exposure,
9
+ bounded persistent batching with retries, and lifecycle-safe beacon/keepalive exit delivery
10
+ with `page_leave`. Cross-origin identity via parent-domain cookies and `linkTo` handoff,
11
+ configurable bot flagging, and opt-in client error and web vitals capture (measurement code
12
+ loads on demand). React provider and hooks support StrictMode and server rendering.
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [b1c1458]
17
+ - kansoku-js@0.1.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nadeem Bitar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,77 @@
1
- # Temporary Holding Version
1
+ # kansoku-react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React bindings for `kansoku-js`, with no runtime dependencies beyond the React and SDK peers.
4
+
5
+ ```bash
6
+ bun add kansoku-js kansoku-react react
7
+ ```
8
+
9
+ ```tsx
10
+ import { KansokuProvider, useTrack, useIdentify, useExperiment } from "kansoku-react"
11
+
12
+ export function App() {
13
+ return (
14
+ <KansokuProvider
15
+ options={{ baseUrl: "https://analytics.example.com", writeKey: "ksk_w_public" }}
16
+ >
17
+ <Signup />
18
+ </KansokuProvider>
19
+ )
20
+ }
21
+
22
+ function Signup() {
23
+ const track = useTrack()
24
+ useIdentify("user_42", { plan: "team" })
25
+ useExperiment("signup_copy", "b")
26
+ return <button onClick={() => track("signup_started")}>Sign up</button>
27
+ }
28
+ ```
29
+
30
+ `KansokuProvider` reads `options` once. Remount with a `key` to reconfigure or change ownership
31
+ mode. It constructs without capture, starts from an effect, stops on cleanup and never calls
32
+ `shutdown()`. StrictMode's setup/cleanup/setup cycle is supported. You can instead pass
33
+ `client={analytics}`; you then own its entire lifecycle, and the provider leaves it untouched.
34
+
35
+ `useKansoku()` returns the client for `flush()`, `reset()`, `group()` and other methods.
36
+ It throws if called without a provider in the browser; server rendering returns a no-op client.
37
+ `useIdentifyOnce(userId, traits?)` follows the same user/client lifecycle as `useIdentify`,
38
+ emitting explicit identify_once v1. It suppresses duplicate StrictMode effect setup; set-once
39
+ is a server trait operation. A later identify v2 may replace the initialized value.
40
+
41
+ `useTrack()` returns a stable tracking callback. `useIdentify(userId, traits?)` identifies on
42
+ ID changes, ignoring traits object identity. An undefined user does not reset identity:
43
+ call `useKansoku().reset()` explicitly on logout. `useExperiment(name, variant, properties?)`
44
+ records exposure from an effect and relies on the core's per-session dedupe.
45
+
46
+ ## Routing
47
+
48
+ React Router and other History API routers require no additional page-view code. Automatic
49
+ capture is enabled by default. For explicit control, disable page autocapture and use a key:
50
+
51
+ ```tsx
52
+ import { usePageView } from "kansoku-react"
53
+ import { useLocation } from "react-router"
54
+
55
+ function PageTracking() {
56
+ const location = useLocation()
57
+ usePageView(location.pathname + location.search, { section: "app" })
58
+ return null
59
+ }
60
+ // Provider options must include autocapture: { pageViews: false } for this pattern.
61
+ ```
62
+
63
+ `usePageView(key, properties?)` emits on mount and key changes. It warns once in development
64
+ when automatic page capture is still enabled, because using both counts views twice.
65
+
66
+ Server rendering produces HTML without browser globals or network capture. Both packages
67
+ are ESM-only; Node 20.19+ (22.12+ on Node 22) supports `require(esm)`. Jest's default
68
+ CommonJS mode needs both packages in its ESM transform allowlist or native ESM configuration.
69
+ TypeScript consumers install compatible `@types/react` (an optional peer for JS consumers).
70
+
71
+ The provider passes `options.autocapture.clientErrors` and `options.autocapture.webVitals` to
72
+ the core unchanged. Both default to `false`. Explicitly enabling them captures sanitized errors
73
+ and document-scoped vitals, including under StrictMode's repeated effect setup/cleanup. Vitals
74
+ use a deferred measurement file and retain their first view's attribution across SPA routes.
75
+ Both events count as server engagement; consider bounce/duration consequences before adoption.
76
+ See the [delivery and privacy guide](../../docs/guides/delivery-and-privacy.md#optional-client-errors-and-web-vitals)
77
+ for limits, finalization, privacy and unsupported measurements.
@@ -0,0 +1,5 @@
1
+ import type { KansokuClient } from "kansoku-js";
2
+ export interface KansokuContextValue {
3
+ client: KansokuClient;
4
+ }
5
+ export declare const KansokuContext: import("react").Context<KansokuContextValue | null>;
@@ -0,0 +1,3 @@
1
+ import type { JsonObject } from "kansoku-js";
2
+ /** Record rendered exposure; kansoku-js owns per-session deduplication, including StrictMode. */
3
+ export declare function useExperiment(experiment: string, variant: string, properties?: JsonObject): void;
@@ -0,0 +1,2 @@
1
+ import type { JsonObject } from "kansoku-js";
2
+ export declare function useIdentify(userId: string | undefined, traits?: JsonObject): void;
@@ -0,0 +1,2 @@
1
+ import type { JsonObject } from "kansoku-js";
2
+ export declare function useIdentifyOnce(userId: string | undefined, traits?: JsonObject): void;
@@ -0,0 +1,2 @@
1
+ import type { KansokuClient } from "kansoku-js";
2
+ export declare function useKansoku(): KansokuClient;
@@ -0,0 +1,2 @@
1
+ import type { JsonObject } from "kansoku-js";
2
+ export declare function usePageView(key: string, properties?: JsonObject): void;
@@ -0,0 +1,2 @@
1
+ import type { KansokuClient } from "kansoku-js";
2
+ export declare function useTrack(): KansokuClient["track"];
@@ -0,0 +1,13 @@
1
+ export { version } from "./version.js";
2
+ export { KansokuProvider } from "./provider.js";
3
+ export type { KansokuProviderProps } from "./provider.js";
4
+ export { KansokuContext } from "./context.js";
5
+ export type { KansokuContextValue } from "./context.js";
6
+ export { createNoopClient } from "./noop-client.js";
7
+ export { useKansoku } from "./hooks/useKansoku.js";
8
+ export { useTrack } from "./hooks/useTrack.js";
9
+ export { usePageView } from "./hooks/usePageView.js";
10
+ export { useIdentify } from "./hooks/useIdentify.js";
11
+ export { useIdentifyOnce } from "./hooks/useIdentifyOnce.js";
12
+ export { useExperiment } from "./hooks/useExperiment.js";
13
+ export type { KansokuClient, KansokuOptions, TrackOptions, JsonObject, IdentifierKind, } from "kansoku-js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ var c="0.1.0";var x=c;import{createKansoku as v}from"kansoku-js";import{useEffect as C,useMemo as j,useState as b}from"react";import{createContext as g}from"react";var u=g(null);var r=()=>{},p=()=>"",f=async()=>{};function a(){let e=Object.freeze({baseUrl:"",writeKey:"",sourceService:"",autoStart:!1,exitTransport:"keepalive",botDetection:"off",crossOriginLink:Object.freeze({accept:!1,allowedOrigins:[]}),flushAt:20,flushIntervalMs:5000,maxQueueSize:1000,maxBatchEvents:100,maxBatchBytes:1048576,maxRetries:0,retryBaseDelayMs:500,requestTimeoutMs:1e4,persistQueue:!1,storage:"memory",storageKeyPrefix:"kansoku",sessionTimeoutMs:1800000,schemaVersions:Object.freeze({}),autocapture:Object.freeze({pageViews:!1,sessions:!1}),optOut:!0,respectDoNotTrack:!1,respectGlobalPrivacyControl:!1,debug:!1,fetch:async()=>new Response(null,{status:204}),now:Date.now,timers:{setTimeout,clearTimeout}});return{linkTo:String,track:r,page:r,identify:r,identifyOnce:r,alias:r,group:r,experiment:r,setIdentifiers:r,reset:r,start:r,stop:r,optOut:r,optIn:r,flush:f,shutdown:f,getAnonymousId:p,getSessionId:p,getUserId:()=>{return},isOptedOut:()=>!0,stats:Object.freeze({queued:0,accepted:0,bestEffortQueued:0,rejected:0,dropped:0}),config:e}}import{jsxDEV as w}from"react/jsx-dev-runtime";function O(e){let[o]=b(()=>({client:e.client??(typeof window>"u"?a():v({...e.options,autoStart:!1})),owned:!e.client})),t=e.client??o.client,s=!e.client&&o.owned;C(()=>{if(!s)return;return t.start(),()=>t.stop()},[t,s]);let n=j(()=>({client:t}),[t]);return w(u.Provider,{value:n,children:e.children},void 0,!1,void 0,this)}import{useContext as E}from"react";var h=a();function i(){let e=E(u);if(e)return e.client;if(typeof window>"u")return h;throw Error("useKansoku must be used inside <KansokuProvider>")}import{useCallback as P}from"react";function R(){let e=i();return P((...o)=>e.track(...o),[e])}import{useEffect as V,useRef as l}from"react";var d=!1;function N(e,o){let t=i(),s=l(o),n=l(void 0);s.current=o,V(()=>{if(n.current?.client===t&&n.current.key===e)return;let y=typeof process<"u"&&process.env?.NODE_ENV==="production";if(t.config.autocapture.pageViews&&!y&&!d)d=!0,console.warn("kansoku-react: usePageView is active but kansoku-js autocapture.pageViews is still enabled; pass autocapture: { pageViews: false } to createKansoku or KansokuProvider options to avoid duplicate page_view events");t.page(s.current),n.current={client:t,key:e}},[t,e])}import{useEffect as T,useRef as k}from"react";function D(e,o){let t=i(),s=k(o);s.current=o;let n=k(void 0);T(()=>{if(!e){n.current=void 0;return}if(n.current?.client===t&&n.current.userId===e)return;t.identify(e,s.current),n.current={client:t,userId:e}},[t,e])}import{useEffect as I,useRef as m}from"react";function J(e,o){let t=i(),s=m(o);s.current=o;let n=m(void 0);I(()=>{if(!e){n.current=void 0;return}if(n.current?.client===t&&n.current.userId===e)return;t.identifyOnce(e,s.current),n.current={client:t,userId:e}},[t,e])}import{useEffect as z,useRef as M}from"react";function S(e,o,t){let s=i(),n=M(t);n.current=t,z(()=>{s.experiment(e,o,n.current)},[s,e,o])}export{u as KansokuContext,O as KansokuProvider,a as createNoopClient,S as useExperiment,D as useIdentify,J as useIdentifyOnce,i as useKansoku,N as usePageView,R as useTrack,x as version};
3
+
4
+ //# debugId=7FACCC7FDB263B3664756E2164756E21
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,19 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/version.ts", "../src/provider.tsx", "../src/context.ts", "../src/noop-client.ts", "../src/hooks/useKansoku.ts", "../src/hooks/useTrack.ts", "../src/hooks/usePageView.ts", "../src/hooks/useIdentify.ts", "../src/hooks/useIdentifyOnce.ts", "../src/hooks/useExperiment.ts"],
4
+ "sourcesContent": [
5
+ "import { version as packageVersion } from \"../package.json\"\nexport const version: string = packageVersion\n",
6
+ "import { createKansoku } from \"kansoku-js\"\nimport type { KansokuClient, KansokuOptions } from \"kansoku-js\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport type { ReactElement, ReactNode } from \"react\"\n\nimport { KansokuContext } from \"./context.js\"\nimport { createNoopClient } from \"./noop-client.js\"\n\nexport type KansokuProviderProps = (\n | { client: KansokuClient; options?: never }\n | { options: KansokuOptions; client?: never }\n) & { children: ReactNode }\n\nexport function KansokuProvider(props: KansokuProviderProps): ReactElement {\n const [initial] = useState(() => ({\n client:\n props.client ??\n (typeof window === \"undefined\"\n ? createNoopClient()\n : createKansoku({ ...props.options!, autoStart: false })),\n owned: !props.client,\n }))\n const client = props.client ?? initial.client\n const ownsClient = !props.client && initial.owned\n useEffect(() => {\n if (!ownsClient) return\n client.start()\n return () => client.stop()\n }, [client, ownsClient])\n const value = useMemo(() => ({ client }), [client])\n return <KansokuContext.Provider value={value}>{props.children}</KansokuContext.Provider>\n}\n",
7
+ "import type { KansokuClient } from \"kansoku-js\"\nimport { createContext } from \"react\"\n\nexport interface KansokuContextValue {\n client: KansokuClient\n}\nexport const KansokuContext = createContext<KansokuContextValue | null>(null)\n",
8
+ "import type { KansokuClient, ResolvedKansokuOptions } from \"kansoku-js\"\n\nconst noop = () => {}\nconst empty = () => \"\"\nconst resolved = async () => {}\nexport function createNoopClient(): KansokuClient {\n const config: ResolvedKansokuOptions = Object.freeze({\n baseUrl: \"\",\n writeKey: \"\",\n sourceService: \"\",\n autoStart: false,\n exitTransport: \"keepalive\",\n botDetection: \"off\",\n crossOriginLink: Object.freeze({ accept: false, allowedOrigins: [] }),\n flushAt: 20,\n flushIntervalMs: 5000,\n maxQueueSize: 1000,\n maxBatchEvents: 100,\n maxBatchBytes: 1048576,\n maxRetries: 0,\n retryBaseDelayMs: 500,\n requestTimeoutMs: 10000,\n persistQueue: false,\n storage: \"memory\",\n storageKeyPrefix: \"kansoku\",\n sessionTimeoutMs: 1800000,\n schemaVersions: Object.freeze({}),\n autocapture: Object.freeze({ pageViews: false, sessions: false }),\n optOut: true,\n respectDoNotTrack: false,\n respectGlobalPrivacyControl: false,\n debug: false,\n fetch: (async () => new Response(null, { status: 204 })) as unknown as typeof fetch,\n now: Date.now,\n timers: { setTimeout, clearTimeout },\n })\n return {\n linkTo: String,\n track: noop,\n page: noop,\n identify: noop,\n identifyOnce: noop,\n alias: noop,\n group: noop,\n experiment: noop,\n setIdentifiers: noop,\n reset: noop,\n start: noop,\n stop: noop,\n optOut: noop,\n optIn: noop,\n flush: resolved,\n shutdown: resolved,\n getAnonymousId: empty,\n getSessionId: empty,\n getUserId: () => undefined,\n isOptedOut: () => true,\n stats: Object.freeze({\n queued: 0,\n accepted: 0,\n bestEffortQueued: 0,\n rejected: 0,\n dropped: 0,\n }),\n config,\n }\n}\n",
9
+ "import type { KansokuClient } from \"kansoku-js\"\nimport { useContext } from \"react\"\n\nimport { KansokuContext } from \"../context.js\"\nimport { createNoopClient } from \"../noop-client.js\"\n\nconst serverClient = createNoopClient()\nexport function useKansoku(): KansokuClient {\n const value = useContext(KansokuContext)\n if (value) return value.client\n if (typeof window === \"undefined\") return serverClient\n throw new Error(\"useKansoku must be used inside <KansokuProvider>\")\n}\n",
10
+ "import type { KansokuClient } from \"kansoku-js\"\nimport { useCallback } from \"react\"\n\nimport { useKansoku } from \"./useKansoku.js\"\n\nexport function useTrack(): KansokuClient[\"track\"] {\n const client = useKansoku()\n return useCallback((...args) => client.track(...args), [client])\n}\n",
11
+ "import type { JsonObject, KansokuClient } from \"kansoku-js\"\nimport { useEffect, useRef } from \"react\"\n\nimport { useKansoku } from \"./useKansoku.js\"\n\ndeclare const process: { env?: { NODE_ENV?: string } }\n\nlet warned = false\nexport function usePageView(key: string, properties?: JsonObject): void {\n const client = useKansoku()\n const latest = useRef(properties)\n const previous = useRef<{ client: KansokuClient; key: string } | undefined>(undefined)\n latest.current = properties\n useEffect(() => {\n if (previous.current?.client === client && previous.current.key === key) return\n const production = typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\"\n if (client.config.autocapture.pageViews && !production && !warned) {\n warned = true\n console.warn(\n \"kansoku-react: usePageView is active but kansoku-js autocapture.pageViews is still enabled; pass autocapture: { pageViews: false } to createKansoku or KansokuProvider options to avoid duplicate page_view events\",\n )\n }\n client.page(latest.current)\n previous.current = { client, key }\n }, [client, key])\n}\n",
12
+ "import type { JsonObject, KansokuClient } from \"kansoku-js\"\nimport { useEffect, useRef } from \"react\"\n\nimport { useKansoku } from \"./useKansoku.js\"\n\nexport function useIdentify(userId: string | undefined, traits?: JsonObject): void {\n const client = useKansoku()\n const latest = useRef(traits)\n latest.current = traits\n const previous = useRef<{ client: KansokuClient; userId: string } | undefined>(undefined)\n useEffect(() => {\n if (!userId) {\n previous.current = undefined\n return\n }\n if (previous.current?.client === client && previous.current.userId === userId) return\n client.identify(userId, latest.current)\n previous.current = { client, userId }\n }, [client, userId])\n}\n",
13
+ "import type { JsonObject, KansokuClient } from \"kansoku-js\"\nimport { useEffect, useRef } from \"react\"\n\nimport { useKansoku } from \"./useKansoku.js\"\n\nexport function useIdentifyOnce(userId: string | undefined, traits?: JsonObject): void {\n const client = useKansoku()\n const latest = useRef(traits)\n latest.current = traits\n const previous = useRef<{ client: KansokuClient; userId: string } | undefined>(undefined)\n useEffect(() => {\n if (!userId) {\n previous.current = undefined\n return\n }\n if (previous.current?.client === client && previous.current.userId === userId) return\n client.identifyOnce(userId, latest.current)\n previous.current = { client, userId }\n }, [client, userId])\n}\n",
14
+ "import type { JsonObject } from \"kansoku-js\"\nimport { useEffect, useRef } from \"react\"\n\nimport { useKansoku } from \"./useKansoku.js\"\n\n/** Record rendered exposure; kansoku-js owns per-session deduplication, including StrictMode. */\nexport function useExperiment(experiment: string, variant: string, properties?: JsonObject): void {\n const client = useKansoku()\n const latest = useRef(properties)\n latest.current = properties\n useEffect(() => {\n client.experiment(experiment, variant, latest.current)\n }, [client, experiment, variant])\n}\n"
15
+ ],
16
+ "mappings": "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",
17
+ "debugId": "7FACCC7FDB263B3664756E2164756E21",
18
+ "names": []
19
+ }
@@ -0,0 +1,2 @@
1
+ import type { KansokuClient } from "kansoku-js";
2
+ export declare function createNoopClient(): KansokuClient;
@@ -0,0 +1,12 @@
1
+ import type { KansokuClient, KansokuOptions } from "kansoku-js";
2
+ import type { ReactElement, ReactNode } from "react";
3
+ export type KansokuProviderProps = ({
4
+ client: KansokuClient;
5
+ options?: never;
6
+ } | {
7
+ options: KansokuOptions;
8
+ client?: never;
9
+ }) & {
10
+ children: ReactNode;
11
+ };
12
+ export declare function KansokuProvider(props: KansokuProviderProps): ReactElement;
@@ -0,0 +1 @@
1
+ export declare const version: string;
package/package.json CHANGED
@@ -1,6 +1,64 @@
1
1
  {
2
2
  "name": "kansoku-react",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "React bindings for kansoku-js",
5
+ "keywords": [
6
+ "analytics",
7
+ "browser",
8
+ "kansoku",
9
+ "react"
10
+ ],
11
+ "homepage": "https://github.com/shinzui/kansoku-ts#readme",
12
+ "license": "MIT",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/shinzui/kansoku-ts.git",
16
+ "directory": "packages/kansoku-react"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "CHANGELOG.md",
22
+ "LICENSE"
23
+ ],
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "main": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "scripts": {
36
+ "build": "bun ../../scripts/build.ts .",
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "bun test"
39
+ },
40
+ "devDependencies": {
41
+ "@testing-library/react": "^16.3.3",
42
+ "@types/react": "^19",
43
+ "@types/react-dom": "^19",
44
+ "kansoku-js": "workspace:*",
45
+ "react": "^19.3.0",
46
+ "react-dom": "^19.3.0"
47
+ },
48
+ "peerDependencies": {
49
+ "@types/react": ">=18",
50
+ "kansoku-js": "^0.1.0",
51
+ "react": "^18.0.0 || ^19.0.0"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "@types/react": {
55
+ "optional": true
56
+ }
57
+ },
58
+ "engines": {
59
+ "node": ">=20.19.0"
60
+ },
61
+ "kansoku": {
62
+ "banner": "\"use client\";"
63
+ }
64
+ }