@shellapps/experience-react 1.0.0 → 1.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/dist/index.d.mts +19 -6
- package/dist/index.d.ts +19 -6
- package/dist/index.js +22 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +22 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
+
import * as _shellapps_experience from '@shellapps/experience';
|
|
4
5
|
import { ExperienceConfig, Experience } from '@shellapps/experience';
|
|
5
6
|
|
|
6
7
|
interface ExperienceProviderProps {
|
|
@@ -34,16 +35,28 @@ declare class ErrorBoundary extends React__default.Component<ErrorBoundaryProps,
|
|
|
34
35
|
render(): string | number | boolean | Iterable<React__default.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
declare function useExperience(): _shellapps_experience.Experience;
|
|
37
39
|
declare function useTrack(): {
|
|
38
|
-
track: (eventName: string, metadata?: Record<string,
|
|
40
|
+
track: (eventName: string, metadata?: Record<string, string>) => void;
|
|
39
41
|
trackPageView: () => void;
|
|
40
42
|
};
|
|
41
43
|
declare function useFlag<T>(flagName: string, defaultValue: T): T;
|
|
42
|
-
|
|
43
|
-
t: (key: string) => string;
|
|
44
|
-
locale:
|
|
45
|
-
|
|
44
|
+
interface TranslationResult {
|
|
45
|
+
t: (key: string, params?: Record<string, string | number>) => string;
|
|
46
|
+
locale: string;
|
|
47
|
+
setLocale: (locale: string) => void;
|
|
48
|
+
locales: Array<{
|
|
49
|
+
code: string;
|
|
50
|
+
name: string;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Translation hook — stub implementation for EXP-5.
|
|
55
|
+
* Currently returns the key with interpolation support.
|
|
56
|
+
* Will fetch from the Experience API when translations are implemented.
|
|
57
|
+
*/
|
|
58
|
+
declare function useTranslation(): TranslationResult;
|
|
46
59
|
|
|
47
60
|
declare const ExperienceContext: React.Context<Experience | null>;
|
|
48
61
|
|
|
49
|
-
export { ErrorBoundary, ExperienceContext, ExperienceProvider, type ExperienceProviderProps, useFlag, useTrack, useTranslation };
|
|
62
|
+
export { ErrorBoundary, ExperienceContext, ExperienceProvider, type ExperienceProviderProps, useExperience, useFlag, useTrack, useTranslation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
+
import * as _shellapps_experience from '@shellapps/experience';
|
|
4
5
|
import { ExperienceConfig, Experience } from '@shellapps/experience';
|
|
5
6
|
|
|
6
7
|
interface ExperienceProviderProps {
|
|
@@ -34,16 +35,28 @@ declare class ErrorBoundary extends React__default.Component<ErrorBoundaryProps,
|
|
|
34
35
|
render(): string | number | boolean | Iterable<React__default.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
declare function useExperience(): _shellapps_experience.Experience;
|
|
37
39
|
declare function useTrack(): {
|
|
38
|
-
track: (eventName: string, metadata?: Record<string,
|
|
40
|
+
track: (eventName: string, metadata?: Record<string, string>) => void;
|
|
39
41
|
trackPageView: () => void;
|
|
40
42
|
};
|
|
41
43
|
declare function useFlag<T>(flagName: string, defaultValue: T): T;
|
|
42
|
-
|
|
43
|
-
t: (key: string) => string;
|
|
44
|
-
locale:
|
|
45
|
-
|
|
44
|
+
interface TranslationResult {
|
|
45
|
+
t: (key: string, params?: Record<string, string | number>) => string;
|
|
46
|
+
locale: string;
|
|
47
|
+
setLocale: (locale: string) => void;
|
|
48
|
+
locales: Array<{
|
|
49
|
+
code: string;
|
|
50
|
+
name: string;
|
|
51
|
+
}>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Translation hook — stub implementation for EXP-5.
|
|
55
|
+
* Currently returns the key with interpolation support.
|
|
56
|
+
* Will fetch from the Experience API when translations are implemented.
|
|
57
|
+
*/
|
|
58
|
+
declare function useTranslation(): TranslationResult;
|
|
46
59
|
|
|
47
60
|
declare const ExperienceContext: React.Context<Experience | null>;
|
|
48
61
|
|
|
49
|
-
export { ErrorBoundary, ExperienceContext, ExperienceProvider, type ExperienceProviderProps, useFlag, useTrack, useTranslation };
|
|
62
|
+
export { ErrorBoundary, ExperienceContext, ExperienceProvider, type ExperienceProviderProps, useExperience, useFlag, useTrack, useTranslation };
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __export(index_exports, {
|
|
|
33
33
|
ErrorBoundary: () => ErrorBoundary,
|
|
34
34
|
ExperienceContext: () => ExperienceContext,
|
|
35
35
|
ExperienceProvider: () => ExperienceProvider,
|
|
36
|
+
useExperience: () => useExperience,
|
|
36
37
|
useFlag: () => useFlag,
|
|
37
38
|
useTrack: () => useTrack,
|
|
38
39
|
useTranslation: () => useTranslation
|
|
@@ -111,7 +112,8 @@ var ErrorBoundary = class extends import_react3.default.Component {
|
|
|
111
112
|
}
|
|
112
113
|
componentDidCatch(error, errorInfo) {
|
|
113
114
|
this.context?.captureError(error, {
|
|
114
|
-
componentStack: errorInfo.componentStack || ""
|
|
115
|
+
extra: { componentStack: errorInfo.componentStack || "" },
|
|
116
|
+
severity: "fatal"
|
|
115
117
|
});
|
|
116
118
|
this.props.onError?.(error, errorInfo);
|
|
117
119
|
}
|
|
@@ -152,26 +154,39 @@ function useExperience() {
|
|
|
152
154
|
}
|
|
153
155
|
function useTrack() {
|
|
154
156
|
const experience = useExperience();
|
|
155
|
-
return {
|
|
157
|
+
return (0, import_react4.useMemo)(() => ({
|
|
156
158
|
track: (eventName, metadata) => experience.track(eventName, metadata),
|
|
157
159
|
trackPageView: () => experience.trackPageView()
|
|
158
|
-
};
|
|
160
|
+
}), [experience]);
|
|
159
161
|
}
|
|
160
162
|
function useFlag(flagName, defaultValue) {
|
|
161
163
|
const experience = useExperience();
|
|
162
164
|
return experience.getFlag(flagName, defaultValue);
|
|
163
165
|
}
|
|
164
166
|
function useTranslation() {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
const [locale, setLocaleState] = (0, import_react4.useState)(
|
|
168
|
+
typeof navigator !== "undefined" ? navigator.language?.split("-")[0] || "en" : "en"
|
|
169
|
+
);
|
|
170
|
+
const t = (0, import_react4.useCallback)((key, params) => {
|
|
171
|
+
let result = key;
|
|
172
|
+
if (params) {
|
|
173
|
+
for (const [k, v] of Object.entries(params)) {
|
|
174
|
+
result = result.replace(new RegExp(`\\{\\{${k}\\}\\}`, "g"), String(v));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}, []);
|
|
179
|
+
const setLocale = (0, import_react4.useCallback)((newLocale) => {
|
|
180
|
+
setLocaleState(newLocale);
|
|
181
|
+
}, []);
|
|
182
|
+
return { t, locale, setLocale, locales: [] };
|
|
169
183
|
}
|
|
170
184
|
// Annotate the CommonJS export names for ESM import in node:
|
|
171
185
|
0 && (module.exports = {
|
|
172
186
|
ErrorBoundary,
|
|
173
187
|
ExperienceContext,
|
|
174
188
|
ExperienceProvider,
|
|
189
|
+
useExperience,
|
|
175
190
|
useFlag,
|
|
176
191
|
useTrack,
|
|
177
192
|
useTranslation
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ExperienceProvider.tsx","../src/context.ts","../src/ErrorBoundary.tsx","../src/hooks.ts"],"sourcesContent":["export { ExperienceProvider } from './ExperienceProvider';\nexport type { ExperienceProviderProps } from './ExperienceProvider';\nexport { ErrorBoundary } from './ErrorBoundary';\nexport { useTrack, useFlag, useTranslation } from './hooks';\nexport { ExperienceContext } from './context';\n","import React, { useEffect, useRef } from 'react';\nimport { Experience } from '@shellapps/experience';\nimport type { ExperienceConfig } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\nexport interface ExperienceProviderProps {\n appId: string;\n apiKey: string;\n profileId?: string;\n options?: Partial<Omit<ExperienceConfig, 'appId' | 'apiKey'>>;\n children: React.ReactNode;\n}\n\nexport function ExperienceProvider({ appId, apiKey, profileId, options, children }: ExperienceProviderProps) {\n const instanceRef = useRef<Experience | null>(null);\n\n if (!instanceRef.current) {\n const instance = Experience.init({ appId, apiKey, ...options });\n if (profileId) instance.identify(profileId);\n instanceRef.current = instance;\n }\n\n useEffect(() => {\n if (profileId && instanceRef.current) {\n instanceRef.current.identify(profileId);\n }\n }, [profileId]);\n\n // data-t auto-tracking\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n let el = e.target as HTMLElement | null;\n while (el) {\n const tid = el.getAttribute?.('data-t');\n if (tid) {\n instanceRef.current?.track('element_click', { elementTid: tid });\n break;\n }\n el = el.parentElement;\n }\n };\n document.addEventListener('click', handler, true);\n return () => document.removeEventListener('click', handler, true);\n }, []);\n\n useEffect(() => {\n return () => {\n instanceRef.current?.shutdown();\n };\n }, []);\n\n return (\n <ExperienceContext.Provider value={instanceRef.current}>\n {children}\n </ExperienceContext.Provider>\n );\n}\n","import { createContext } from 'react';\nimport type { Experience } from '@shellapps/experience';\n\nexport const ExperienceContext = createContext<Experience | null>(null);\n","import React from 'react';\nimport type { Experience } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\ninterface ErrorBoundaryProps {\n fallback?: React.ReactNode;\n showCommentForm?: boolean;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n comment: string;\n submitted: boolean;\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = ExperienceContext;\n declare context: Experience | null;\n\n state: ErrorBoundaryState = {\n hasError: false,\n error: null,\n comment: '',\n submitted: false,\n };\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.context?.captureError(error, {\n componentStack: errorInfo.componentStack || '',\n });\n this.props.onError?.(error, errorInfo);\n }\n\n private handleSubmitComment = () => {\n if (this.state.comment.trim() && this.state.error) {\n this.context?.captureMessage(\n `User feedback: ${this.state.comment}`,\n 'info',\n );\n this.setState({ submitted: true });\n }\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div style={{ padding: 20, textAlign: 'center' }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error?.message}</p>\n {this.props.showCommentForm && !this.state.submitted && (\n <div>\n <textarea\n placeholder=\"Tell us what happened...\"\n value={this.state.comment}\n onChange={(e) => this.setState({ comment: e.target.value })}\n style={{ width: '100%', minHeight: 80, marginTop: 10 }}\n />\n <button onClick={this.handleSubmitComment} style={{ marginTop: 8 }}>\n Submit\n </button>\n </div>\n )}\n {this.state.submitted && <p>Thank you for your feedback!</p>}\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n","import { useContext } from 'react';\nimport { ExperienceContext } from './context';\n\
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ExperienceProvider.tsx","../src/context.ts","../src/ErrorBoundary.tsx","../src/hooks.ts"],"sourcesContent":["export { ExperienceProvider } from './ExperienceProvider';\nexport type { ExperienceProviderProps } from './ExperienceProvider';\nexport { ErrorBoundary } from './ErrorBoundary';\nexport { useExperience, useTrack, useFlag, useTranslation } from './hooks';\nexport { ExperienceContext } from './context';\n","import React, { useEffect, useRef } from 'react';\nimport { Experience } from '@shellapps/experience';\nimport type { ExperienceConfig } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\nexport interface ExperienceProviderProps {\n appId: string;\n apiKey: string;\n profileId?: string;\n options?: Partial<Omit<ExperienceConfig, 'appId' | 'apiKey'>>;\n children: React.ReactNode;\n}\n\nexport function ExperienceProvider({ appId, apiKey, profileId, options, children }: ExperienceProviderProps) {\n const instanceRef = useRef<Experience | null>(null);\n\n if (!instanceRef.current) {\n const instance = Experience.init({ appId, apiKey, ...options });\n if (profileId) instance.identify(profileId);\n instanceRef.current = instance;\n }\n\n useEffect(() => {\n if (profileId && instanceRef.current) {\n instanceRef.current.identify(profileId);\n }\n }, [profileId]);\n\n // data-t auto-tracking\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n let el = e.target as HTMLElement | null;\n while (el) {\n const tid = el.getAttribute?.('data-t');\n if (tid) {\n instanceRef.current?.track('element_click', { elementTid: tid });\n break;\n }\n el = el.parentElement;\n }\n };\n document.addEventListener('click', handler, true);\n return () => document.removeEventListener('click', handler, true);\n }, []);\n\n useEffect(() => {\n return () => {\n instanceRef.current?.shutdown();\n };\n }, []);\n\n return (\n <ExperienceContext.Provider value={instanceRef.current}>\n {children}\n </ExperienceContext.Provider>\n );\n}\n","import { createContext } from 'react';\nimport type { Experience } from '@shellapps/experience';\n\nexport const ExperienceContext = createContext<Experience | null>(null);\n","import React from 'react';\nimport type { Experience } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\ninterface ErrorBoundaryProps {\n fallback?: React.ReactNode;\n showCommentForm?: boolean;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n comment: string;\n submitted: boolean;\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = ExperienceContext;\n declare context: Experience | null;\n\n state: ErrorBoundaryState = {\n hasError: false,\n error: null,\n comment: '',\n submitted: false,\n };\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.context?.captureError(error, {\n extra: { componentStack: errorInfo.componentStack || '' },\n severity: 'fatal' as any,\n });\n this.props.onError?.(error, errorInfo);\n }\n\n private handleSubmitComment = () => {\n if (this.state.comment.trim() && this.state.error) {\n this.context?.captureMessage(\n `User feedback: ${this.state.comment}`,\n 'info',\n );\n this.setState({ submitted: true });\n }\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div style={{ padding: 20, textAlign: 'center' }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error?.message}</p>\n {this.props.showCommentForm && !this.state.submitted && (\n <div>\n <textarea\n placeholder=\"Tell us what happened...\"\n value={this.state.comment}\n onChange={(e) => this.setState({ comment: e.target.value })}\n style={{ width: '100%', minHeight: 80, marginTop: 10 }}\n />\n <button onClick={this.handleSubmitComment} style={{ marginTop: 8 }}>\n Submit\n </button>\n </div>\n )}\n {this.state.submitted && <p>Thank you for your feedback!</p>}\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n","import { useContext, useState, useCallback, useMemo } from 'react';\nimport { ExperienceContext } from './context';\n\nexport function useExperience() {\n const ctx = useContext(ExperienceContext);\n if (!ctx) throw new Error('useExperience must be used within ExperienceProvider');\n return ctx;\n}\n\nexport function useTrack() {\n const experience = useExperience();\n return useMemo(() => ({\n track: (eventName: string, metadata?: Record<string, string>) => experience.track(eventName, metadata),\n trackPageView: () => experience.trackPageView(),\n }), [experience]);\n}\n\nexport function useFlag<T>(flagName: string, defaultValue: T): T {\n const experience = useExperience();\n return experience.getFlag(flagName, defaultValue);\n}\n\ninterface TranslationResult {\n t: (key: string, params?: Record<string, string | number>) => string;\n locale: string;\n setLocale: (locale: string) => void;\n locales: Array<{ code: string; name: string }>;\n}\n\n/**\n * Translation hook — stub implementation for EXP-5.\n * Currently returns the key with interpolation support.\n * Will fetch from the Experience API when translations are implemented.\n */\nexport function useTranslation(): TranslationResult {\n const [locale, setLocaleState] = useState(\n typeof navigator !== 'undefined' ? navigator.language?.split('-')[0] || 'en' : 'en'\n );\n\n const t = useCallback((key: string, params?: Record<string, string | number>): string => {\n let result = key;\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n result = result.replace(new RegExp(`\\\\{\\\\{${k}\\\\}\\\\}`, 'g'), String(v));\n }\n }\n return result;\n }, []);\n\n const setLocale = useCallback((newLocale: string) => {\n setLocaleState(newLocale);\n }, []);\n\n return { t, locale, setLocale, locales: [] };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","React","import_react"]}
|
package/dist/index.mjs
CHANGED
|
@@ -70,7 +70,8 @@ var ErrorBoundary = class extends React2.Component {
|
|
|
70
70
|
}
|
|
71
71
|
componentDidCatch(error, errorInfo) {
|
|
72
72
|
this.context?.captureError(error, {
|
|
73
|
-
componentStack: errorInfo.componentStack || ""
|
|
73
|
+
extra: { componentStack: errorInfo.componentStack || "" },
|
|
74
|
+
severity: "fatal"
|
|
74
75
|
});
|
|
75
76
|
this.props.onError?.(error, errorInfo);
|
|
76
77
|
}
|
|
@@ -103,7 +104,7 @@ var ErrorBoundary = class extends React2.Component {
|
|
|
103
104
|
ErrorBoundary.contextType = ExperienceContext;
|
|
104
105
|
|
|
105
106
|
// src/hooks.ts
|
|
106
|
-
import { useContext } from "react";
|
|
107
|
+
import { useContext, useState, useCallback, useMemo } from "react";
|
|
107
108
|
function useExperience() {
|
|
108
109
|
const ctx = useContext(ExperienceContext);
|
|
109
110
|
if (!ctx) throw new Error("useExperience must be used within ExperienceProvider");
|
|
@@ -111,25 +112,38 @@ function useExperience() {
|
|
|
111
112
|
}
|
|
112
113
|
function useTrack() {
|
|
113
114
|
const experience = useExperience();
|
|
114
|
-
return {
|
|
115
|
+
return useMemo(() => ({
|
|
115
116
|
track: (eventName, metadata) => experience.track(eventName, metadata),
|
|
116
117
|
trackPageView: () => experience.trackPageView()
|
|
117
|
-
};
|
|
118
|
+
}), [experience]);
|
|
118
119
|
}
|
|
119
120
|
function useFlag(flagName, defaultValue) {
|
|
120
121
|
const experience = useExperience();
|
|
121
122
|
return experience.getFlag(flagName, defaultValue);
|
|
122
123
|
}
|
|
123
124
|
function useTranslation() {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
const [locale, setLocaleState] = useState(
|
|
126
|
+
typeof navigator !== "undefined" ? navigator.language?.split("-")[0] || "en" : "en"
|
|
127
|
+
);
|
|
128
|
+
const t = useCallback((key, params) => {
|
|
129
|
+
let result = key;
|
|
130
|
+
if (params) {
|
|
131
|
+
for (const [k, v] of Object.entries(params)) {
|
|
132
|
+
result = result.replace(new RegExp(`\\{\\{${k}\\}\\}`, "g"), String(v));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}, []);
|
|
137
|
+
const setLocale = useCallback((newLocale) => {
|
|
138
|
+
setLocaleState(newLocale);
|
|
139
|
+
}, []);
|
|
140
|
+
return { t, locale, setLocale, locales: [] };
|
|
128
141
|
}
|
|
129
142
|
export {
|
|
130
143
|
ErrorBoundary,
|
|
131
144
|
ExperienceContext,
|
|
132
145
|
ExperienceProvider,
|
|
146
|
+
useExperience,
|
|
133
147
|
useFlag,
|
|
134
148
|
useTrack,
|
|
135
149
|
useTranslation
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ExperienceProvider.tsx","../src/context.ts","../src/ErrorBoundary.tsx","../src/hooks.ts"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport { Experience } from '@shellapps/experience';\nimport type { ExperienceConfig } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\nexport interface ExperienceProviderProps {\n appId: string;\n apiKey: string;\n profileId?: string;\n options?: Partial<Omit<ExperienceConfig, 'appId' | 'apiKey'>>;\n children: React.ReactNode;\n}\n\nexport function ExperienceProvider({ appId, apiKey, profileId, options, children }: ExperienceProviderProps) {\n const instanceRef = useRef<Experience | null>(null);\n\n if (!instanceRef.current) {\n const instance = Experience.init({ appId, apiKey, ...options });\n if (profileId) instance.identify(profileId);\n instanceRef.current = instance;\n }\n\n useEffect(() => {\n if (profileId && instanceRef.current) {\n instanceRef.current.identify(profileId);\n }\n }, [profileId]);\n\n // data-t auto-tracking\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n let el = e.target as HTMLElement | null;\n while (el) {\n const tid = el.getAttribute?.('data-t');\n if (tid) {\n instanceRef.current?.track('element_click', { elementTid: tid });\n break;\n }\n el = el.parentElement;\n }\n };\n document.addEventListener('click', handler, true);\n return () => document.removeEventListener('click', handler, true);\n }, []);\n\n useEffect(() => {\n return () => {\n instanceRef.current?.shutdown();\n };\n }, []);\n\n return (\n <ExperienceContext.Provider value={instanceRef.current}>\n {children}\n </ExperienceContext.Provider>\n );\n}\n","import { createContext } from 'react';\nimport type { Experience } from '@shellapps/experience';\n\nexport const ExperienceContext = createContext<Experience | null>(null);\n","import React from 'react';\nimport type { Experience } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\ninterface ErrorBoundaryProps {\n fallback?: React.ReactNode;\n showCommentForm?: boolean;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n comment: string;\n submitted: boolean;\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = ExperienceContext;\n declare context: Experience | null;\n\n state: ErrorBoundaryState = {\n hasError: false,\n error: null,\n comment: '',\n submitted: false,\n };\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.context?.captureError(error, {\n componentStack: errorInfo.componentStack || '',\n });\n this.props.onError?.(error, errorInfo);\n }\n\n private handleSubmitComment = () => {\n if (this.state.comment.trim() && this.state.error) {\n this.context?.captureMessage(\n `User feedback: ${this.state.comment}`,\n 'info',\n );\n this.setState({ submitted: true });\n }\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div style={{ padding: 20, textAlign: 'center' }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error?.message}</p>\n {this.props.showCommentForm && !this.state.submitted && (\n <div>\n <textarea\n placeholder=\"Tell us what happened...\"\n value={this.state.comment}\n onChange={(e) => this.setState({ comment: e.target.value })}\n style={{ width: '100%', minHeight: 80, marginTop: 10 }}\n />\n <button onClick={this.handleSubmitComment} style={{ marginTop: 8 }}>\n Submit\n </button>\n </div>\n )}\n {this.state.submitted && <p>Thank you for your feedback!</p>}\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n","import { useContext } from 'react';\nimport { ExperienceContext } from './context';\n\
|
|
1
|
+
{"version":3,"sources":["../src/ExperienceProvider.tsx","../src/context.ts","../src/ErrorBoundary.tsx","../src/hooks.ts"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\nimport { Experience } from '@shellapps/experience';\nimport type { ExperienceConfig } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\nexport interface ExperienceProviderProps {\n appId: string;\n apiKey: string;\n profileId?: string;\n options?: Partial<Omit<ExperienceConfig, 'appId' | 'apiKey'>>;\n children: React.ReactNode;\n}\n\nexport function ExperienceProvider({ appId, apiKey, profileId, options, children }: ExperienceProviderProps) {\n const instanceRef = useRef<Experience | null>(null);\n\n if (!instanceRef.current) {\n const instance = Experience.init({ appId, apiKey, ...options });\n if (profileId) instance.identify(profileId);\n instanceRef.current = instance;\n }\n\n useEffect(() => {\n if (profileId && instanceRef.current) {\n instanceRef.current.identify(profileId);\n }\n }, [profileId]);\n\n // data-t auto-tracking\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n let el = e.target as HTMLElement | null;\n while (el) {\n const tid = el.getAttribute?.('data-t');\n if (tid) {\n instanceRef.current?.track('element_click', { elementTid: tid });\n break;\n }\n el = el.parentElement;\n }\n };\n document.addEventListener('click', handler, true);\n return () => document.removeEventListener('click', handler, true);\n }, []);\n\n useEffect(() => {\n return () => {\n instanceRef.current?.shutdown();\n };\n }, []);\n\n return (\n <ExperienceContext.Provider value={instanceRef.current}>\n {children}\n </ExperienceContext.Provider>\n );\n}\n","import { createContext } from 'react';\nimport type { Experience } from '@shellapps/experience';\n\nexport const ExperienceContext = createContext<Experience | null>(null);\n","import React from 'react';\nimport type { Experience } from '@shellapps/experience';\nimport { ExperienceContext } from './context';\n\ninterface ErrorBoundaryProps {\n fallback?: React.ReactNode;\n showCommentForm?: boolean;\n onError?: (error: Error, errorInfo: React.ErrorInfo) => void;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n comment: string;\n submitted: boolean;\n}\n\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n static contextType = ExperienceContext;\n declare context: Experience | null;\n\n state: ErrorBoundaryState = {\n hasError: false,\n error: null,\n comment: '',\n submitted: false,\n };\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return { hasError: true, error };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n this.context?.captureError(error, {\n extra: { componentStack: errorInfo.componentStack || '' },\n severity: 'fatal' as any,\n });\n this.props.onError?.(error, errorInfo);\n }\n\n private handleSubmitComment = () => {\n if (this.state.comment.trim() && this.state.error) {\n this.context?.captureMessage(\n `User feedback: ${this.state.comment}`,\n 'info',\n );\n this.setState({ submitted: true });\n }\n };\n\n render() {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n return (\n <div style={{ padding: 20, textAlign: 'center' }}>\n <h2>Something went wrong</h2>\n <p>{this.state.error?.message}</p>\n {this.props.showCommentForm && !this.state.submitted && (\n <div>\n <textarea\n placeholder=\"Tell us what happened...\"\n value={this.state.comment}\n onChange={(e) => this.setState({ comment: e.target.value })}\n style={{ width: '100%', minHeight: 80, marginTop: 10 }}\n />\n <button onClick={this.handleSubmitComment} style={{ marginTop: 8 }}>\n Submit\n </button>\n </div>\n )}\n {this.state.submitted && <p>Thank you for your feedback!</p>}\n </div>\n );\n }\n\n return this.props.children;\n }\n}\n","import { useContext, useState, useCallback, useMemo } from 'react';\nimport { ExperienceContext } from './context';\n\nexport function useExperience() {\n const ctx = useContext(ExperienceContext);\n if (!ctx) throw new Error('useExperience must be used within ExperienceProvider');\n return ctx;\n}\n\nexport function useTrack() {\n const experience = useExperience();\n return useMemo(() => ({\n track: (eventName: string, metadata?: Record<string, string>) => experience.track(eventName, metadata),\n trackPageView: () => experience.trackPageView(),\n }), [experience]);\n}\n\nexport function useFlag<T>(flagName: string, defaultValue: T): T {\n const experience = useExperience();\n return experience.getFlag(flagName, defaultValue);\n}\n\ninterface TranslationResult {\n t: (key: string, params?: Record<string, string | number>) => string;\n locale: string;\n setLocale: (locale: string) => void;\n locales: Array<{ code: string; name: string }>;\n}\n\n/**\n * Translation hook — stub implementation for EXP-5.\n * Currently returns the key with interpolation support.\n * Will fetch from the Experience API when translations are implemented.\n */\nexport function useTranslation(): TranslationResult {\n const [locale, setLocaleState] = useState(\n typeof navigator !== 'undefined' ? navigator.language?.split('-')[0] || 'en' : 'en'\n );\n\n const t = useCallback((key: string, params?: Record<string, string | number>): string => {\n let result = key;\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n result = result.replace(new RegExp(`\\\\{\\\\{${k}\\\\}\\\\}`, 'g'), String(v));\n }\n }\n return result;\n }, []);\n\n const setLocale = useCallback((newLocale: string) => {\n setLocaleState(newLocale);\n }, []);\n\n return { t, locale, setLocale, locales: [] };\n}\n"],"mappings":"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","names":["React","jsx","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shellapps/experience-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "React SDK for @shellapps/experience",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"url": "git+https://github.com/ShellTechnology/shellapps-js.git",
|
|
44
44
|
"directory": "packages/experience-react"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "984bce1c38a4fe679cfe034601efe88c85ec6e8b"
|
|
47
47
|
}
|