@guidelytech/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/README.md +38 -2
- package/dist/index.cjs +165 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +39 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +134 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -3
package/README.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @guidelytech/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React provider and hooks for Guidely. Wraps `@guidelytech/sdk-core`; works with React 18/19, SSR and
|
|
4
|
+
Strict Mode.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pnpm add @guidelytech/react
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { GuidelyProvider, useGuidely } from "@guidelytech/react";
|
|
12
|
+
|
|
13
|
+
export function App({ children }) {
|
|
14
|
+
return (
|
|
15
|
+
<GuidelyProvider projectId="pk_dev_…" apiUrl="http://localhost:3000" user={{ id: "u1", traits: { role: "admin" } }}>
|
|
16
|
+
{children}
|
|
17
|
+
</GuidelyProvider>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function HelpMenu() {
|
|
22
|
+
const guidely = useGuidely();
|
|
23
|
+
return <button onClick={() => guidely.startGuide("new-user-onboarding")}>Restart tour</button>;
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
| Export | Description |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `GuidelyProvider` | Accepts every `GuidelyOptions` field plus `user?: { id, traits?, account? }` and `children`. Creates the client inside an effect (never during SSR), destroys it on unmount; Strict Mode's double invoke yields exactly one live client. Changing `projectId`/`environment`/`apiUrl` recreates the client; changing `user` re-identifies (`undefined` resets). |
|
|
30
|
+
| `useGuidely()` | The client, or a no-op proxy on the server / before mount (methods return `false`, `[]`, `null` or resolved promises). |
|
|
31
|
+
| `useGuidelyReady()` | `true` once config is loaded. |
|
|
32
|
+
| `useGuidelyIdentify(userId, traits?, account?)` | Effect helper that identifies when the arguments change. |
|
|
33
|
+
| `useGuidelyEvent(event, handler)` | Subscribes for the component lifetime (latest handler is used). |
|
|
34
|
+
| `useChecklistProgress(idOrKey)` | Live `{ completedTaskIds, completedAt, dismissedAt }`. |
|
|
35
|
+
| `useGuideState(idOrKey)` | Live `{ active, completed, stepId, stepIndex, guide }`. |
|
|
36
|
+
| `noopClient` | The no-op client instance. |
|
|
37
|
+
|
|
38
|
+
Types re-exported: `GuidelyClient`, `GuidelyOptions`, `GuidelyEvents`, `GuidelyUser`,
|
|
39
|
+
`ChecklistProgressState`, `PublishedGuide`, `GuideState`, `GuidelyProviderProps`.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.tsx
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
GuidelyProvider: () => GuidelyProvider,
|
|
25
|
+
noopClient: () => noopClient,
|
|
26
|
+
useChecklistProgress: () => useChecklistProgress,
|
|
27
|
+
useGuideState: () => useGuideState,
|
|
28
|
+
useGuidely: () => useGuidely,
|
|
29
|
+
useGuidelyEvent: () => useGuidelyEvent,
|
|
30
|
+
useGuidelyIdentify: () => useGuidelyIdentify,
|
|
31
|
+
useGuidelyReady: () => useGuidelyReady
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(index_exports);
|
|
34
|
+
var import_sdk_core = require("@guidelytech/sdk-core");
|
|
35
|
+
var import_react = require("react");
|
|
36
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
37
|
+
var GuidelyContext = (0, import_react.createContext)(null);
|
|
38
|
+
function GuidelyProvider({ children, user, ...options }) {
|
|
39
|
+
const [client, setClient] = (0, import_react.useState)(null);
|
|
40
|
+
const optionsRef = (0, import_react.useRef)(options);
|
|
41
|
+
optionsRef.current = options;
|
|
42
|
+
const { projectId, environment, apiUrl } = options;
|
|
43
|
+
(0, import_react.useEffect)(() => {
|
|
44
|
+
if (typeof window === "undefined" || !projectId) return;
|
|
45
|
+
const c = (0, import_sdk_core.createGuidely)({ ...optionsRef.current, projectId, environment, apiUrl });
|
|
46
|
+
setClient(c);
|
|
47
|
+
return () => {
|
|
48
|
+
c.destroy();
|
|
49
|
+
setClient((cur) => cur === c ? null : cur);
|
|
50
|
+
};
|
|
51
|
+
}, [projectId, environment, apiUrl]);
|
|
52
|
+
const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : "";
|
|
53
|
+
const hadUser = (0, import_react.useRef)(false);
|
|
54
|
+
(0, import_react.useEffect)(() => {
|
|
55
|
+
if (!client) return;
|
|
56
|
+
if (user && user.id) {
|
|
57
|
+
hadUser.current = true;
|
|
58
|
+
void client.identify(user.id, user.traits, user.account);
|
|
59
|
+
} else if (hadUser.current) {
|
|
60
|
+
hadUser.current = false;
|
|
61
|
+
client.reset();
|
|
62
|
+
}
|
|
63
|
+
}, [client, userKey]);
|
|
64
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GuidelyContext.Provider, { value: client, children });
|
|
65
|
+
}
|
|
66
|
+
var NOOP_RESULTS = {
|
|
67
|
+
init: Promise.resolve(),
|
|
68
|
+
ready: Promise.resolve(),
|
|
69
|
+
identify: Promise.resolve(),
|
|
70
|
+
setAccount: Promise.resolve(),
|
|
71
|
+
updateTraits: Promise.resolve(),
|
|
72
|
+
refresh: Promise.resolve(),
|
|
73
|
+
startGuide: false,
|
|
74
|
+
getActiveGuide: null,
|
|
75
|
+
getGuides: [],
|
|
76
|
+
getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },
|
|
77
|
+
isGuideCompleted: false,
|
|
78
|
+
on: () => {
|
|
79
|
+
},
|
|
80
|
+
getState: { ready: false, destroyed: false },
|
|
81
|
+
getContext: null
|
|
82
|
+
};
|
|
83
|
+
var noopClient = new Proxy({}, {
|
|
84
|
+
get(_target, prop) {
|
|
85
|
+
if (prop === "options") return { projectId: "" };
|
|
86
|
+
if (typeof prop !== "string") return void 0;
|
|
87
|
+
return () => NOOP_RESULTS[prop];
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
function useGuidely() {
|
|
91
|
+
return (0, import_react.useContext)(GuidelyContext) ?? noopClient;
|
|
92
|
+
}
|
|
93
|
+
function useGuidelyReady() {
|
|
94
|
+
const client = (0, import_react.useContext)(GuidelyContext);
|
|
95
|
+
const [ready, setReady] = (0, import_react.useState)(false);
|
|
96
|
+
(0, import_react.useEffect)(() => {
|
|
97
|
+
if (!client) {
|
|
98
|
+
setReady(false);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (client.getState().ready) setReady(true);
|
|
102
|
+
return client.on("ready", () => setReady(true));
|
|
103
|
+
}, [client]);
|
|
104
|
+
return ready;
|
|
105
|
+
}
|
|
106
|
+
function useGuidelyIdentify(userId, traits, account) {
|
|
107
|
+
const client = (0, import_react.useContext)(GuidelyContext);
|
|
108
|
+
const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);
|
|
109
|
+
(0, import_react.useEffect)(() => {
|
|
110
|
+
if (!client || !userId) return;
|
|
111
|
+
void client.identify(userId, traits, account);
|
|
112
|
+
}, [client, key]);
|
|
113
|
+
}
|
|
114
|
+
function useGuidelyEvent(event, handler) {
|
|
115
|
+
const client = (0, import_react.useContext)(GuidelyContext);
|
|
116
|
+
const ref = (0, import_react.useRef)(handler);
|
|
117
|
+
ref.current = handler;
|
|
118
|
+
(0, import_react.useEffect)(() => {
|
|
119
|
+
if (!client) return;
|
|
120
|
+
const cb = ((...args) => ref.current(...args));
|
|
121
|
+
return client.on(event, cb);
|
|
122
|
+
}, [client, event]);
|
|
123
|
+
}
|
|
124
|
+
function useChecklistProgress(idOrKey) {
|
|
125
|
+
const client = (0, import_react.useContext)(GuidelyContext);
|
|
126
|
+
const [progress, setProgress] = (0, import_react.useState)({ completedTaskIds: [], completedAt: null, dismissedAt: null });
|
|
127
|
+
(0, import_react.useEffect)(() => {
|
|
128
|
+
if (!client) return;
|
|
129
|
+
const update = () => setProgress(client.getChecklistProgress(idOrKey));
|
|
130
|
+
update();
|
|
131
|
+
const offs = [client.on("ready", update), client.on("identify", update), client.on("checklist:task", update), client.on("checklist:complete", update)];
|
|
132
|
+
return () => offs.forEach((off) => off());
|
|
133
|
+
}, [client, idOrKey]);
|
|
134
|
+
return progress;
|
|
135
|
+
}
|
|
136
|
+
function useGuideState(idOrKey) {
|
|
137
|
+
const client = (0, import_react.useContext)(GuidelyContext);
|
|
138
|
+
const [state, setState] = (0, import_react.useState)({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });
|
|
139
|
+
(0, import_react.useEffect)(() => {
|
|
140
|
+
if (!client) return;
|
|
141
|
+
const matches = (g) => g.id === idOrKey || g.key === idOrKey;
|
|
142
|
+
const compute = () => {
|
|
143
|
+
const guide = client.getGuides().find(matches) ?? null;
|
|
144
|
+
const active = client.getActiveGuide();
|
|
145
|
+
const s = client.getState().activeGuide;
|
|
146
|
+
setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? s?.stepId ?? null : null, stepIndex: active && matches(active) ? s?.stepIndex ?? -1 : -1, guide });
|
|
147
|
+
};
|
|
148
|
+
compute();
|
|
149
|
+
const offs = ["ready", "identify", "guide:start", "guide:step", "guide:complete", "guide:dismiss", "guide:skip"].map((e) => client.on(e, compute));
|
|
150
|
+
return () => offs.forEach((off) => off());
|
|
151
|
+
}, [client, idOrKey]);
|
|
152
|
+
return state;
|
|
153
|
+
}
|
|
154
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
155
|
+
0 && (module.exports = {
|
|
156
|
+
GuidelyProvider,
|
|
157
|
+
noopClient,
|
|
158
|
+
useChecklistProgress,
|
|
159
|
+
useGuideState,
|
|
160
|
+
useGuidely,
|
|
161
|
+
useGuidelyEvent,
|
|
162
|
+
useGuidelyIdentify,
|
|
163
|
+
useGuidelyReady
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useRef, useState, type ReactNode } from \"react\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide } from \"@guidelytech/sdk-core\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n children?: ReactNode;\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const c = createGuidely({ ...optionsRef.current, projectId, environment, apiUrl });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n return <GuidelyContext.Provider value={client}>{children}</GuidelyContext.Provider>;\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (typeof prop !== \"string\") return undefined;\n return () => NOOP_RESULTS[prop];\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
|
|
4
|
+
export { ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
|
|
5
|
+
|
|
6
|
+
interface GuidelyProviderProps extends Omit<GuidelyOptions, "user"> {
|
|
7
|
+
/** Identify this user as soon as the client is ready; `undefined` resets the identity. */
|
|
8
|
+
user?: GuidelyUser | null;
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates one Guidely client for the subtree. The client is created inside an effect (never
|
|
13
|
+
* during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.
|
|
14
|
+
*/
|
|
15
|
+
declare function GuidelyProvider({ children, user, ...options }: GuidelyProviderProps): react.JSX.Element;
|
|
16
|
+
/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */
|
|
17
|
+
declare const noopClient: GuidelyClient;
|
|
18
|
+
/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */
|
|
19
|
+
declare function useGuidely(): GuidelyClient;
|
|
20
|
+
/** True once the client has loaded its configuration. */
|
|
21
|
+
declare function useGuidelyReady(): boolean;
|
|
22
|
+
/** Identifies the user whenever the arguments change. */
|
|
23
|
+
declare function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser["account"]): void;
|
|
24
|
+
/** Subscribes to a client event for the lifetime of the component. */
|
|
25
|
+
declare function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void;
|
|
26
|
+
/** Live checklist progress for a checklist guide (by id or key). */
|
|
27
|
+
declare function useChecklistProgress(idOrKey: string): ChecklistProgressState;
|
|
28
|
+
interface GuideState {
|
|
29
|
+
/** The guide is currently showing. */
|
|
30
|
+
active: boolean;
|
|
31
|
+
completed: boolean;
|
|
32
|
+
stepId: string | null;
|
|
33
|
+
stepIndex: number;
|
|
34
|
+
guide: PublishedGuide | null;
|
|
35
|
+
}
|
|
36
|
+
/** Live state of a guide (by id or key): active, completed, current step. */
|
|
37
|
+
declare function useGuideState(idOrKey: string): GuideState;
|
|
38
|
+
|
|
39
|
+
export { type GuideState, GuidelyProvider, type GuidelyProviderProps, noopClient, useChecklistProgress, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { PublishedGuide, GuidelyOptions, GuidelyUser, GuidelyClient, ChecklistProgressState, GuidelyEvents } from '@guidelytech/sdk-core';
|
|
4
|
+
export { ChecklistProgressState, GuidelyClient, GuidelyEvents, GuidelyOptions, GuidelyUser, PublishedGuide } from '@guidelytech/sdk-core';
|
|
5
|
+
|
|
6
|
+
interface GuidelyProviderProps extends Omit<GuidelyOptions, "user"> {
|
|
7
|
+
/** Identify this user as soon as the client is ready; `undefined` resets the identity. */
|
|
8
|
+
user?: GuidelyUser | null;
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates one Guidely client for the subtree. The client is created inside an effect (never
|
|
13
|
+
* during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.
|
|
14
|
+
*/
|
|
15
|
+
declare function GuidelyProvider({ children, user, ...options }: GuidelyProviderProps): react.JSX.Element;
|
|
16
|
+
/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */
|
|
17
|
+
declare const noopClient: GuidelyClient;
|
|
18
|
+
/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */
|
|
19
|
+
declare function useGuidely(): GuidelyClient;
|
|
20
|
+
/** True once the client has loaded its configuration. */
|
|
21
|
+
declare function useGuidelyReady(): boolean;
|
|
22
|
+
/** Identifies the user whenever the arguments change. */
|
|
23
|
+
declare function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser["account"]): void;
|
|
24
|
+
/** Subscribes to a client event for the lifetime of the component. */
|
|
25
|
+
declare function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void;
|
|
26
|
+
/** Live checklist progress for a checklist guide (by id or key). */
|
|
27
|
+
declare function useChecklistProgress(idOrKey: string): ChecklistProgressState;
|
|
28
|
+
interface GuideState {
|
|
29
|
+
/** The guide is currently showing. */
|
|
30
|
+
active: boolean;
|
|
31
|
+
completed: boolean;
|
|
32
|
+
stepId: string | null;
|
|
33
|
+
stepIndex: number;
|
|
34
|
+
guide: PublishedGuide | null;
|
|
35
|
+
}
|
|
36
|
+
/** Live state of a guide (by id or key): active, completed, current step. */
|
|
37
|
+
declare function useGuideState(idOrKey: string): GuideState;
|
|
38
|
+
|
|
39
|
+
export { type GuideState, GuidelyProvider, type GuidelyProviderProps, noopClient, useChecklistProgress, useGuideState, useGuidely, useGuidelyEvent, useGuidelyIdentify, useGuidelyReady };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/index.tsx
|
|
4
|
+
import { createGuidely } from "@guidelytech/sdk-core";
|
|
5
|
+
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var GuidelyContext = createContext(null);
|
|
8
|
+
function GuidelyProvider({ children, user, ...options }) {
|
|
9
|
+
const [client, setClient] = useState(null);
|
|
10
|
+
const optionsRef = useRef(options);
|
|
11
|
+
optionsRef.current = options;
|
|
12
|
+
const { projectId, environment, apiUrl } = options;
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (typeof window === "undefined" || !projectId) return;
|
|
15
|
+
const c = createGuidely({ ...optionsRef.current, projectId, environment, apiUrl });
|
|
16
|
+
setClient(c);
|
|
17
|
+
return () => {
|
|
18
|
+
c.destroy();
|
|
19
|
+
setClient((cur) => cur === c ? null : cur);
|
|
20
|
+
};
|
|
21
|
+
}, [projectId, environment, apiUrl]);
|
|
22
|
+
const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : "";
|
|
23
|
+
const hadUser = useRef(false);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!client) return;
|
|
26
|
+
if (user && user.id) {
|
|
27
|
+
hadUser.current = true;
|
|
28
|
+
void client.identify(user.id, user.traits, user.account);
|
|
29
|
+
} else if (hadUser.current) {
|
|
30
|
+
hadUser.current = false;
|
|
31
|
+
client.reset();
|
|
32
|
+
}
|
|
33
|
+
}, [client, userKey]);
|
|
34
|
+
return /* @__PURE__ */ jsx(GuidelyContext.Provider, { value: client, children });
|
|
35
|
+
}
|
|
36
|
+
var NOOP_RESULTS = {
|
|
37
|
+
init: Promise.resolve(),
|
|
38
|
+
ready: Promise.resolve(),
|
|
39
|
+
identify: Promise.resolve(),
|
|
40
|
+
setAccount: Promise.resolve(),
|
|
41
|
+
updateTraits: Promise.resolve(),
|
|
42
|
+
refresh: Promise.resolve(),
|
|
43
|
+
startGuide: false,
|
|
44
|
+
getActiveGuide: null,
|
|
45
|
+
getGuides: [],
|
|
46
|
+
getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },
|
|
47
|
+
isGuideCompleted: false,
|
|
48
|
+
on: () => {
|
|
49
|
+
},
|
|
50
|
+
getState: { ready: false, destroyed: false },
|
|
51
|
+
getContext: null
|
|
52
|
+
};
|
|
53
|
+
var noopClient = new Proxy({}, {
|
|
54
|
+
get(_target, prop) {
|
|
55
|
+
if (prop === "options") return { projectId: "" };
|
|
56
|
+
if (typeof prop !== "string") return void 0;
|
|
57
|
+
return () => NOOP_RESULTS[prop];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
function useGuidely() {
|
|
61
|
+
return useContext(GuidelyContext) ?? noopClient;
|
|
62
|
+
}
|
|
63
|
+
function useGuidelyReady() {
|
|
64
|
+
const client = useContext(GuidelyContext);
|
|
65
|
+
const [ready, setReady] = useState(false);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!client) {
|
|
68
|
+
setReady(false);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (client.getState().ready) setReady(true);
|
|
72
|
+
return client.on("ready", () => setReady(true));
|
|
73
|
+
}, [client]);
|
|
74
|
+
return ready;
|
|
75
|
+
}
|
|
76
|
+
function useGuidelyIdentify(userId, traits, account) {
|
|
77
|
+
const client = useContext(GuidelyContext);
|
|
78
|
+
const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (!client || !userId) return;
|
|
81
|
+
void client.identify(userId, traits, account);
|
|
82
|
+
}, [client, key]);
|
|
83
|
+
}
|
|
84
|
+
function useGuidelyEvent(event, handler) {
|
|
85
|
+
const client = useContext(GuidelyContext);
|
|
86
|
+
const ref = useRef(handler);
|
|
87
|
+
ref.current = handler;
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (!client) return;
|
|
90
|
+
const cb = ((...args) => ref.current(...args));
|
|
91
|
+
return client.on(event, cb);
|
|
92
|
+
}, [client, event]);
|
|
93
|
+
}
|
|
94
|
+
function useChecklistProgress(idOrKey) {
|
|
95
|
+
const client = useContext(GuidelyContext);
|
|
96
|
+
const [progress, setProgress] = useState({ completedTaskIds: [], completedAt: null, dismissedAt: null });
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (!client) return;
|
|
99
|
+
const update = () => setProgress(client.getChecklistProgress(idOrKey));
|
|
100
|
+
update();
|
|
101
|
+
const offs = [client.on("ready", update), client.on("identify", update), client.on("checklist:task", update), client.on("checklist:complete", update)];
|
|
102
|
+
return () => offs.forEach((off) => off());
|
|
103
|
+
}, [client, idOrKey]);
|
|
104
|
+
return progress;
|
|
105
|
+
}
|
|
106
|
+
function useGuideState(idOrKey) {
|
|
107
|
+
const client = useContext(GuidelyContext);
|
|
108
|
+
const [state, setState] = useState({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (!client) return;
|
|
111
|
+
const matches = (g) => g.id === idOrKey || g.key === idOrKey;
|
|
112
|
+
const compute = () => {
|
|
113
|
+
const guide = client.getGuides().find(matches) ?? null;
|
|
114
|
+
const active = client.getActiveGuide();
|
|
115
|
+
const s = client.getState().activeGuide;
|
|
116
|
+
setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? s?.stepId ?? null : null, stepIndex: active && matches(active) ? s?.stepIndex ?? -1 : -1, guide });
|
|
117
|
+
};
|
|
118
|
+
compute();
|
|
119
|
+
const offs = ["ready", "identify", "guide:start", "guide:step", "guide:complete", "guide:dismiss", "guide:skip"].map((e) => client.on(e, compute));
|
|
120
|
+
return () => offs.forEach((off) => off());
|
|
121
|
+
}, [client, idOrKey]);
|
|
122
|
+
return state;
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
GuidelyProvider,
|
|
126
|
+
noopClient,
|
|
127
|
+
useChecklistProgress,
|
|
128
|
+
useGuideState,
|
|
129
|
+
useGuidely,
|
|
130
|
+
useGuidelyEvent,
|
|
131
|
+
useGuidelyIdentify,
|
|
132
|
+
useGuidelyReady
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx"],"sourcesContent":["import { createGuidely, type ChecklistProgressState, type GuidelyClient, type GuidelyEvents, type GuidelyOptions, type GuidelyUser, type PublishedGuide } from \"@guidelytech/sdk-core\";\nimport { createContext, useContext, useEffect, useRef, useState, type ReactNode } from \"react\";\n\nexport type { GuidelyClient, GuidelyOptions, GuidelyEvents, GuidelyUser, ChecklistProgressState, PublishedGuide } from \"@guidelytech/sdk-core\";\n\nconst GuidelyContext = createContext<GuidelyClient | null>(null);\n\nexport interface GuidelyProviderProps extends Omit<GuidelyOptions, \"user\"> {\n /** Identify this user as soon as the client is ready; `undefined` resets the identity. */\n user?: GuidelyUser | null;\n children?: ReactNode;\n}\n\n/**\n * Creates one Guidely client for the subtree. The client is created inside an effect (never\n * during SSR) and destroyed on unmount, so React Strict Mode's double-invoke is harmless.\n */\nexport function GuidelyProvider({ children, user, ...options }: GuidelyProviderProps) {\n const [client, setClient] = useState<GuidelyClient | null>(null);\n const optionsRef = useRef(options);\n optionsRef.current = options;\n const { projectId, environment, apiUrl } = options;\n\n useEffect(() => {\n if (typeof window === \"undefined\" || !projectId) return;\n const c = createGuidely({ ...optionsRef.current, projectId, environment, apiUrl });\n setClient(c);\n return () => {\n c.destroy();\n setClient((cur) => (cur === c ? null : cur));\n };\n }, [projectId, environment, apiUrl]);\n\n const userKey = user ? JSON.stringify([user.id, user.traits ?? null, user.account ?? null]) : \"\";\n const hadUser = useRef(false);\n useEffect(() => {\n if (!client) return;\n if (user && user.id) {\n hadUser.current = true;\n void client.identify(user.id, user.traits, user.account);\n } else if (hadUser.current) {\n hadUser.current = false;\n client.reset();\n }\n }, [client, userKey]);\n\n return <GuidelyContext.Provider value={client}>{children}</GuidelyContext.Provider>;\n}\n\nconst NOOP_RESULTS: Record<string, unknown> = {\n init: Promise.resolve(),\n ready: Promise.resolve(),\n identify: Promise.resolve(),\n setAccount: Promise.resolve(),\n updateTraits: Promise.resolve(),\n refresh: Promise.resolve(),\n startGuide: false,\n getActiveGuide: null,\n getGuides: [],\n getChecklistProgress: { completedTaskIds: [], completedAt: null, dismissedAt: null },\n isGuideCompleted: false,\n on: () => {},\n getState: { ready: false, destroyed: false },\n getContext: null,\n};\n\n/** A client that ignores every call; returned by `useGuidely()` on the server and before the provider mounts. */\nexport const noopClient: GuidelyClient = new Proxy({} as GuidelyClient, {\n get(_target, prop) {\n if (prop === \"options\") return { projectId: \"\" };\n if (typeof prop !== \"string\") return undefined;\n return () => NOOP_RESULTS[prop];\n },\n});\n\n/** The Guidely client, or a no-op client during SSR / before the provider has mounted. */\nexport function useGuidely(): GuidelyClient {\n return useContext(GuidelyContext) ?? noopClient;\n}\n\n/** True once the client has loaded its configuration. */\nexport function useGuidelyReady(): boolean {\n const client = useContext(GuidelyContext);\n const [ready, setReady] = useState(false);\n useEffect(() => {\n if (!client) {\n setReady(false);\n return;\n }\n if (client.getState().ready) setReady(true);\n return client.on(\"ready\", () => setReady(true));\n }, [client]);\n return ready;\n}\n\n/** Identifies the user whenever the arguments change. */\nexport function useGuidelyIdentify(userId: string | null | undefined, traits?: Record<string, unknown>, account?: GuidelyUser[\"account\"]): void {\n const client = useContext(GuidelyContext);\n const key = JSON.stringify([userId ?? null, traits ?? null, account ?? null]);\n useEffect(() => {\n if (!client || !userId) return;\n void client.identify(userId, traits, account);\n }, [client, key]);\n}\n\n/** Subscribes to a client event for the lifetime of the component. */\nexport function useGuidelyEvent<K extends keyof GuidelyEvents>(event: K, handler: GuidelyEvents[K]): void {\n const client = useContext(GuidelyContext);\n const ref = useRef(handler);\n ref.current = handler;\n useEffect(() => {\n if (!client) return;\n const cb = ((...args: unknown[]) => (ref.current as (...a: unknown[]) => void)(...args)) as GuidelyEvents[K];\n return client.on(event, cb);\n }, [client, event]);\n}\n\n/** Live checklist progress for a checklist guide (by id or key). */\nexport function useChecklistProgress(idOrKey: string): ChecklistProgressState {\n const client = useContext(GuidelyContext);\n const [progress, setProgress] = useState<ChecklistProgressState>({ completedTaskIds: [], completedAt: null, dismissedAt: null });\n useEffect(() => {\n if (!client) return;\n const update = () => setProgress(client.getChecklistProgress(idOrKey));\n update();\n const offs = [client.on(\"ready\", update), client.on(\"identify\", update), client.on(\"checklist:task\", update), client.on(\"checklist:complete\", update)];\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return progress;\n}\n\nexport interface GuideState {\n /** The guide is currently showing. */\n active: boolean;\n completed: boolean;\n stepId: string | null;\n stepIndex: number;\n guide: PublishedGuide | null;\n}\n\n/** Live state of a guide (by id or key): active, completed, current step. */\nexport function useGuideState(idOrKey: string): GuideState {\n const client = useContext(GuidelyContext);\n const [state, setState] = useState<GuideState>({ active: false, completed: false, stepId: null, stepIndex: -1, guide: null });\n useEffect(() => {\n if (!client) return;\n const matches = (g: PublishedGuide) => g.id === idOrKey || g.key === idOrKey;\n const compute = () => {\n const guide = client.getGuides().find(matches) ?? null;\n const active = client.getActiveGuide();\n const s = client.getState().activeGuide;\n setState({ active: !!active && matches(active), completed: client.isGuideCompleted(idOrKey), stepId: active && matches(active) ? ((s as { stepId?: string | null } | null)?.stepId ?? null) : null, stepIndex: active && matches(active) ? ((s as { stepIndex?: number } | null)?.stepIndex ?? -1) : -1, guide });\n };\n compute();\n const offs = ([\"ready\", \"identify\", \"guide:start\", \"guide:step\", \"guide:complete\", \"guide:dismiss\", \"guide:skip\"] as const).map((e) => client.on(e, compute));\n return () => offs.forEach((off) => off());\n }, [client, idOrKey]);\n return state;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guidelytech/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React provider and hooks for Guidely",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@guidelytech/shared": "0.1.0",
|
|
24
|
+
"@guidelytech/sdk-core": "0.1.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"tsup": "^8.5.1",
|
|
28
|
+
"typescript": "^5.9.3",
|
|
29
|
+
"vitest": "^3.2.7",
|
|
30
|
+
"happy-dom": "^17.6.3",
|
|
31
|
+
"eslint": "^9.39.5",
|
|
32
|
+
"@eslint/js": "^9.39.5",
|
|
33
|
+
"typescript-eslint": "^8.46.0",
|
|
34
|
+
"react": "19.1.10",
|
|
35
|
+
"react-dom": "19.1.10",
|
|
36
|
+
"@types/react": "^19.1.0",
|
|
37
|
+
"@types/react-dom": "^19.1.0",
|
|
38
|
+
"@testing-library/react": "^16.3.3"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": ">=18.0.0",
|
|
42
|
+
"react-dom": ">=18.0.0"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/parmarg/Guidely.git",
|
|
50
|
+
"directory": "packages/react"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/parmarg/Guidely/tree/main/packages/react#readme",
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/parmarg/Guidely/issues"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [
|
|
57
|
+
"guidely",
|
|
58
|
+
"product-adoption",
|
|
59
|
+
"onboarding",
|
|
60
|
+
"product-tour",
|
|
61
|
+
"in-app-guidance",
|
|
62
|
+
"react"
|
|
63
|
+
],
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "tsup",
|
|
66
|
+
"dev": "tsup --watch",
|
|
67
|
+
"typecheck": "tsc --noEmit",
|
|
68
|
+
"test": "vitest run",
|
|
69
|
+
"lint": "eslint src",
|
|
70
|
+
"clean": "rm -rf dist"
|
|
71
|
+
}
|
|
6
72
|
}
|