@outlit/browser 1.3.0 → 1.4.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.
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
- import { h as OutlitOptions, U as UserIdentity, O as Outlit, B as BillingOptions } from '../tracker-OMgVDwlV.mjs';
4
+ import { U as UserIdentity, h as OutlitOptions, O as Outlit, B as BillingOptions } from '../tracker-OMgVDwlV.mjs';
5
5
  import { BrowserTrackOptions, BrowserIdentifyOptions } from '@outlit/core';
6
6
  export { BrowserIdentifyOptions, BrowserTrackOptions, CustomerIdentifier, ExplicitJourneyStage, TrackerConfig } from '@outlit/core';
7
7
 
@@ -13,20 +13,8 @@ interface OutlitContextValue {
13
13
  disableTracking: () => void;
14
14
  }
15
15
  declare const OutlitContext: react.Context<OutlitContextValue>;
16
- interface OutlitProviderProps extends Omit<OutlitOptions, "trackPageviews"> {
16
+ interface OutlitProviderBaseProps {
17
17
  children: ReactNode;
18
- /**
19
- * Whether to automatically track pageviews.
20
- * When true (default), tracks pageviews on route changes.
21
- */
22
- trackPageviews?: boolean;
23
- /**
24
- * Whether to start tracking automatically on mount.
25
- * Set to false if you need to wait for user consent.
26
- * Call enableTracking() (from useOutlit hook) after consent is obtained.
27
- * @default true
28
- */
29
- autoTrack?: boolean;
30
18
  /**
31
19
  * Current user identity.
32
20
  * When provided with email or userId, calls setUser() to identify the user.
@@ -52,46 +40,83 @@ interface OutlitProviderProps extends Omit<OutlitOptions, "trackPageviews"> {
52
40
  user?: UserIdentity | null;
53
41
  }
54
42
  /**
55
- * Outlit Provider component.
56
- * Initializes the client and provides it to child components via context.
43
+ * Props for using a pre-existing Outlit instance.
44
+ * The provider will use this instance directly without creating a new one.
45
+ * The caller owns the instance lifecycle — shutdown() will NOT be called on unmount.
57
46
  *
58
47
  * @example
59
48
  * ```tsx
60
- * // layout.tsx - Auto tracking (default)
49
+ * import { Outlit } from '@outlit/browser'
61
50
  * import { OutlitProvider } from '@outlit/browser/react'
62
51
  *
63
- * export default function RootLayout({ children }) {
52
+ * const outlit = new Outlit({ publicKey: 'pk_xxx', trackPageviews: false })
53
+ *
54
+ * function App() {
55
+ * const user = useAuth()
64
56
  * return (
65
- * <OutlitProvider publicKey="pk_xxx" trackPageviews>
57
+ * <OutlitProvider client={outlit} user={user ? { email: user.email } : null}>
66
58
  * {children}
67
59
  * </OutlitProvider>
68
60
  * )
69
61
  * }
70
62
  * ```
63
+ */
64
+ type NeverOutlitOptions = {
65
+ [K in keyof OutlitOptions]?: never;
66
+ };
67
+ interface OutlitProviderClientProps extends OutlitProviderBaseProps, NeverOutlitOptions {
68
+ /** An existing Outlit instance to use. Config props are ignored when this is provided. */
69
+ client: Outlit;
70
+ }
71
+ /**
72
+ * Props for creating a new Outlit instance internally.
73
+ * This is the default behavior — the provider creates and owns the instance.
74
+ */
75
+ interface OutlitProviderConfigProps extends OutlitProviderBaseProps, Omit<OutlitOptions, "trackPageviews"> {
76
+ client?: never;
77
+ /**
78
+ * Whether to automatically track pageviews.
79
+ * When true (default), tracks pageviews on route changes.
80
+ */
81
+ trackPageviews?: boolean;
82
+ /**
83
+ * Whether to start tracking automatically on mount.
84
+ * Set to false if you need to wait for user consent.
85
+ * Call enableTracking() (from useOutlit hook) after consent is obtained.
86
+ * @default true
87
+ */
88
+ autoTrack?: boolean;
89
+ }
90
+ type OutlitProviderProps = OutlitProviderClientProps | OutlitProviderConfigProps;
91
+ /**
92
+ * Outlit Provider component.
93
+ * Initializes the client and provides it to child components via context.
94
+ *
95
+ * Can be used in two ways:
96
+ *
97
+ * 1. **Config mode** (default): Pass `publicKey` and config options to create a new instance.
98
+ * 2. **Client mode**: Pass an existing `client` instance for shared imperative + React usage.
71
99
  *
72
100
  * @example
73
101
  * ```tsx
74
- * // layout.tsx - With consent management
75
- * import { OutlitProvider } from '@outlit/browser/react'
76
- *
77
- * export default function RootLayout({ children }) {
78
- * return (
79
- * <OutlitProvider publicKey="pk_xxx" autoTrack={false}>
80
- * {children}
81
- * </OutlitProvider>
82
- * )
83
- * }
102
+ * // Config mode provider creates and owns the instance
103
+ * <OutlitProvider publicKey="pk_xxx" trackPageviews>
104
+ * {children}
105
+ * </OutlitProvider>
106
+ * ```
84
107
  *
85
- * // ConsentBanner.tsx
86
- * import { useOutlit } from '@outlit/browser/react'
108
+ * @example
109
+ * ```tsx
110
+ * // Client mode — use an existing instance
111
+ * const outlit = new Outlit({ publicKey: 'pk_xxx' })
112
+ * outlit.track('pageview') // imperative usage
87
113
  *
88
- * function ConsentBanner() {
89
- * const { enableTracking } = useOutlit()
90
- * return <button onClick={enableTracking}>Accept Cookies</button>
91
- * }
114
+ * <OutlitProvider client={outlit} user={user}>
115
+ * {children}
116
+ * </OutlitProvider>
92
117
  * ```
93
118
  */
94
- declare function OutlitProvider({ children, publicKey, apiHost, trackPageviews, trackForms, formFieldDenylist, flushInterval, autoTrack, autoIdentify, user, }: OutlitProviderProps): react_jsx_runtime.JSX.Element;
119
+ declare function OutlitProvider(props: OutlitProviderProps): react_jsx_runtime.JSX.Element;
95
120
 
96
121
  interface UseOutlitReturn {
97
122
  /**
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ReactNode } from 'react';
4
- import { h as OutlitOptions, U as UserIdentity, O as Outlit, B as BillingOptions } from '../tracker-OMgVDwlV.js';
4
+ import { U as UserIdentity, h as OutlitOptions, O as Outlit, B as BillingOptions } from '../tracker-OMgVDwlV.js';
5
5
  import { BrowserTrackOptions, BrowserIdentifyOptions } from '@outlit/core';
6
6
  export { BrowserIdentifyOptions, BrowserTrackOptions, CustomerIdentifier, ExplicitJourneyStage, TrackerConfig } from '@outlit/core';
7
7
 
@@ -13,20 +13,8 @@ interface OutlitContextValue {
13
13
  disableTracking: () => void;
14
14
  }
15
15
  declare const OutlitContext: react.Context<OutlitContextValue>;
16
- interface OutlitProviderProps extends Omit<OutlitOptions, "trackPageviews"> {
16
+ interface OutlitProviderBaseProps {
17
17
  children: ReactNode;
18
- /**
19
- * Whether to automatically track pageviews.
20
- * When true (default), tracks pageviews on route changes.
21
- */
22
- trackPageviews?: boolean;
23
- /**
24
- * Whether to start tracking automatically on mount.
25
- * Set to false if you need to wait for user consent.
26
- * Call enableTracking() (from useOutlit hook) after consent is obtained.
27
- * @default true
28
- */
29
- autoTrack?: boolean;
30
18
  /**
31
19
  * Current user identity.
32
20
  * When provided with email or userId, calls setUser() to identify the user.
@@ -52,46 +40,83 @@ interface OutlitProviderProps extends Omit<OutlitOptions, "trackPageviews"> {
52
40
  user?: UserIdentity | null;
53
41
  }
54
42
  /**
55
- * Outlit Provider component.
56
- * Initializes the client and provides it to child components via context.
43
+ * Props for using a pre-existing Outlit instance.
44
+ * The provider will use this instance directly without creating a new one.
45
+ * The caller owns the instance lifecycle — shutdown() will NOT be called on unmount.
57
46
  *
58
47
  * @example
59
48
  * ```tsx
60
- * // layout.tsx - Auto tracking (default)
49
+ * import { Outlit } from '@outlit/browser'
61
50
  * import { OutlitProvider } from '@outlit/browser/react'
62
51
  *
63
- * export default function RootLayout({ children }) {
52
+ * const outlit = new Outlit({ publicKey: 'pk_xxx', trackPageviews: false })
53
+ *
54
+ * function App() {
55
+ * const user = useAuth()
64
56
  * return (
65
- * <OutlitProvider publicKey="pk_xxx" trackPageviews>
57
+ * <OutlitProvider client={outlit} user={user ? { email: user.email } : null}>
66
58
  * {children}
67
59
  * </OutlitProvider>
68
60
  * )
69
61
  * }
70
62
  * ```
63
+ */
64
+ type NeverOutlitOptions = {
65
+ [K in keyof OutlitOptions]?: never;
66
+ };
67
+ interface OutlitProviderClientProps extends OutlitProviderBaseProps, NeverOutlitOptions {
68
+ /** An existing Outlit instance to use. Config props are ignored when this is provided. */
69
+ client: Outlit;
70
+ }
71
+ /**
72
+ * Props for creating a new Outlit instance internally.
73
+ * This is the default behavior — the provider creates and owns the instance.
74
+ */
75
+ interface OutlitProviderConfigProps extends OutlitProviderBaseProps, Omit<OutlitOptions, "trackPageviews"> {
76
+ client?: never;
77
+ /**
78
+ * Whether to automatically track pageviews.
79
+ * When true (default), tracks pageviews on route changes.
80
+ */
81
+ trackPageviews?: boolean;
82
+ /**
83
+ * Whether to start tracking automatically on mount.
84
+ * Set to false if you need to wait for user consent.
85
+ * Call enableTracking() (from useOutlit hook) after consent is obtained.
86
+ * @default true
87
+ */
88
+ autoTrack?: boolean;
89
+ }
90
+ type OutlitProviderProps = OutlitProviderClientProps | OutlitProviderConfigProps;
91
+ /**
92
+ * Outlit Provider component.
93
+ * Initializes the client and provides it to child components via context.
94
+ *
95
+ * Can be used in two ways:
96
+ *
97
+ * 1. **Config mode** (default): Pass `publicKey` and config options to create a new instance.
98
+ * 2. **Client mode**: Pass an existing `client` instance for shared imperative + React usage.
71
99
  *
72
100
  * @example
73
101
  * ```tsx
74
- * // layout.tsx - With consent management
75
- * import { OutlitProvider } from '@outlit/browser/react'
76
- *
77
- * export default function RootLayout({ children }) {
78
- * return (
79
- * <OutlitProvider publicKey="pk_xxx" autoTrack={false}>
80
- * {children}
81
- * </OutlitProvider>
82
- * )
83
- * }
102
+ * // Config mode provider creates and owns the instance
103
+ * <OutlitProvider publicKey="pk_xxx" trackPageviews>
104
+ * {children}
105
+ * </OutlitProvider>
106
+ * ```
84
107
  *
85
- * // ConsentBanner.tsx
86
- * import { useOutlit } from '@outlit/browser/react'
108
+ * @example
109
+ * ```tsx
110
+ * // Client mode — use an existing instance
111
+ * const outlit = new Outlit({ publicKey: 'pk_xxx' })
112
+ * outlit.track('pageview') // imperative usage
87
113
  *
88
- * function ConsentBanner() {
89
- * const { enableTracking } = useOutlit()
90
- * return <button onClick={enableTracking}>Accept Cookies</button>
91
- * }
114
+ * <OutlitProvider client={outlit} user={user}>
115
+ * {children}
116
+ * </OutlitProvider>
92
117
  * ```
93
118
  */
94
- declare function OutlitProvider({ children, publicKey, apiHost, trackPageviews, trackForms, formFieldDenylist, flushInterval, autoTrack, autoIdentify, user, }: OutlitProviderProps): react_jsx_runtime.JSX.Element;
119
+ declare function OutlitProvider(props: OutlitProviderProps): react_jsx_runtime.JSX.Element;
95
120
 
96
121
  interface UseOutlitReturn {
97
122
  /**
@@ -1073,48 +1073,78 @@ var OutlitContext = (0, import_react.createContext)({
1073
1073
  disableTracking: () => {
1074
1074
  }
1075
1075
  });
1076
- function OutlitProvider({
1077
- children,
1078
- publicKey,
1079
- apiHost,
1080
- trackPageviews = true,
1081
- trackForms = true,
1082
- formFieldDenylist,
1083
- flushInterval,
1084
- autoTrack = true,
1085
- autoIdentify = true,
1086
- user
1087
- }) {
1076
+ function OutlitProvider(props) {
1077
+ const { children, user } = props;
1088
1078
  const outlitRef = (0, import_react.useRef)(null);
1089
1079
  const initializedRef = (0, import_react.useRef)(false);
1080
+ const isExternalClientRef = (0, import_react.useRef)(false);
1081
+ const [isInitialized, setIsInitialized] = (0, import_react.useState)(false);
1090
1082
  const [isTrackingEnabled, setIsTrackingEnabled] = (0, import_react.useState)(false);
1091
1083
  (0, import_react.useEffect)(() => {
1092
1084
  if (initializedRef.current) return;
1093
- outlitRef.current = new Outlit({
1094
- publicKey,
1095
- apiHost,
1096
- trackPageviews,
1097
- trackForms,
1098
- formFieldDenylist,
1099
- flushInterval,
1100
- autoTrack,
1101
- autoIdentify
1102
- });
1085
+ if (props.client) {
1086
+ if (process.env.NODE_ENV !== "production") {
1087
+ const configKeys = [
1088
+ "publicKey",
1089
+ "apiHost",
1090
+ "trackPageviews",
1091
+ "trackForms",
1092
+ "formFieldDenylist",
1093
+ "flushInterval",
1094
+ "autoTrack",
1095
+ "autoIdentify",
1096
+ "trackCalendarEmbeds",
1097
+ "trackEngagement",
1098
+ "idleTimeout"
1099
+ ];
1100
+ const conflicting = configKeys.filter(
1101
+ (k) => k in props && props[k] !== void 0
1102
+ );
1103
+ if (conflicting.length > 0) {
1104
+ console.warn(
1105
+ `[Outlit] Both \`client\` and config props (${conflicting.join(", ")}) were provided to OutlitProvider. The \`client\` instance will be used and config props will be ignored.`
1106
+ );
1107
+ }
1108
+ }
1109
+ outlitRef.current = props.client;
1110
+ isExternalClientRef.current = true;
1111
+ } else {
1112
+ const {
1113
+ publicKey,
1114
+ apiHost,
1115
+ trackPageviews = true,
1116
+ trackForms = true,
1117
+ formFieldDenylist,
1118
+ flushInterval,
1119
+ autoTrack = true,
1120
+ autoIdentify = true,
1121
+ trackCalendarEmbeds,
1122
+ trackEngagement,
1123
+ idleTimeout
1124
+ } = props;
1125
+ outlitRef.current = new Outlit({
1126
+ publicKey,
1127
+ apiHost,
1128
+ trackPageviews,
1129
+ trackForms,
1130
+ formFieldDenylist,
1131
+ flushInterval,
1132
+ autoTrack,
1133
+ autoIdentify,
1134
+ trackCalendarEmbeds,
1135
+ trackEngagement,
1136
+ idleTimeout
1137
+ });
1138
+ }
1103
1139
  initializedRef.current = true;
1140
+ setIsInitialized(true);
1104
1141
  setIsTrackingEnabled(outlitRef.current.isEnabled());
1105
1142
  return () => {
1106
- outlitRef.current?.shutdown();
1143
+ if (!isExternalClientRef.current) {
1144
+ outlitRef.current?.shutdown();
1145
+ }
1107
1146
  };
1108
- }, [
1109
- publicKey,
1110
- apiHost,
1111
- trackPageviews,
1112
- trackForms,
1113
- formFieldDenylist,
1114
- flushInterval,
1115
- autoTrack,
1116
- autoIdentify
1117
- ]);
1147
+ }, []);
1118
1148
  (0, import_react.useEffect)(() => {
1119
1149
  if (!outlitRef.current) return;
1120
1150
  if (user && (user.email || user.userId)) {
@@ -1140,7 +1170,7 @@ function OutlitProvider({
1140
1170
  {
1141
1171
  value: {
1142
1172
  outlit: outlitRef.current,
1143
- isInitialized: initializedRef.current,
1173
+ isInitialized,
1144
1174
  isTrackingEnabled,
1145
1175
  enableTracking,
1146
1176
  disableTracking