onboard-engine 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robin Fors
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 ADDED
@@ -0,0 +1,227 @@
1
+ <p align="center">
2
+ <img src="logo.png" alt="Onboard Engine Logo" width="200" />
3
+ </p>
4
+
5
+ # Onboard Engine
6
+
7
+ **A modern, lightweight, and customizable onboarding library for React and Next.js applications.**
8
+
9
+ `onboard-engine` provides a seamless way to guide users through your application using an animated focus overlay, tooltips, and persistent state management. Built with smooth CSS transitions and **Cookies** for state persistence.
10
+
11
+ ![License](https://img.shields.io/npm/l/onboard-engine)
12
+ ![Version](https://img.shields.io/npm/v/onboard-engine)
13
+
14
+ ## Features
15
+
16
+ - **Smart Focus Overlay:** Dim the background and highlight the target element.
17
+ - **Deeply Customizable:** Custom renderers for buttons and styling options for the overlay.
18
+ - **State Persistence:** Remembers the user's progress across page reloads using cookies.
19
+ - **Automatic Navigation:** Seamlessly transitions between steps on different pages.
20
+ - **Interactive:** Supports click automation and draggable tooltips.
21
+ - **SSR Compatible:** Built with Server-Side Rendering (Next.js) in mind.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install onboard-engine
27
+ # or
28
+ yarn add onboard-engine
29
+ # or
30
+ pnpm add onboard-engine
31
+ ```
32
+
33
+ ## Getting Started
34
+
35
+ ### 1. Import Styles
36
+
37
+ Import the necessary CSS in your global stylesheet or root component (e.g., `_app.tsx` or `layout.tsx`).
38
+
39
+ ```tsx
40
+ import 'onboard-engine/dist/index.css';
41
+ ```
42
+
43
+ ### 2. Define Configuration
44
+
45
+ Create your onboarding configuration object. This defines the steps, metadata, and optional styling.
46
+
47
+ ```tsx
48
+ import { OnboardingConfig } from 'onboard-engine';
49
+
50
+ const onboardingConfig: OnboardingConfig = {
51
+ metadata: {
52
+ name: 'user-onboarding',
53
+ draggable: true, // Allow users to drag the tooltip
54
+ inOrder: true, // Default true. If false, steps can be activated out of order based on URL match.
55
+ },
56
+ steps: [
57
+ {
58
+ title: 'Welcome!',
59
+ description: 'Let us show you around the dashboard.',
60
+ attribute: 'welcome-header',
61
+ urlMatch: '/',
62
+ },
63
+ {
64
+ title: 'Create Project',
65
+ description: 'Click here to start a new project.',
66
+ attribute: 'create-btn',
67
+ navigate: '/dashboard', // Navigate to this page when clicking next
68
+ urlMatch: '/home', // This step is active when on /home
69
+ subSteps: [
70
+ {
71
+ title: 'Project Name',
72
+ description: 'Enter a unique name for your project.',
73
+ attribute: 'project-name-input',
74
+ },
75
+ ],
76
+ },
77
+ ],
78
+ onOnboardingComplete: () => {
79
+ console.log('Onboarding finished!');
80
+ }
81
+ };
82
+ ```
83
+
84
+ ### 3. Wrap Your Application
85
+
86
+ Wrap your application (or the part you want to onboard) with the `OnboardingProvider`.
87
+
88
+ ```tsx
89
+ import { OnboardingProvider } from 'onboard-engine';
90
+
91
+ export default function App({ children }) {
92
+ return (
93
+ <OnboardingProvider config={onboardingConfig}>
94
+ {children}
95
+ </OnboardingProvider>
96
+ );
97
+ }
98
+ ```
99
+
100
+ ### 4. Tag Your Elements
101
+
102
+ Add the `data-onboarding-id` attribute to the elements you want to highlight. This must match the `attribute` defined in your config steps.
103
+
104
+ ```tsx
105
+ <h1 data-onboarding-id="welcome-header">Welcome to My App</h1>
106
+ <button data-onboarding-id="create-btn">Create Project</button>
107
+ <input data-onboarding-id="project-name-input" type="text" />
108
+ ```
109
+
110
+ ## Advanced Configuration
111
+
112
+ ### Custom Styling
113
+
114
+ You can customize the appearance of the overlay and tooltip through the `style` property in the config. This accepts standard React CSS properties for each element.
115
+
116
+ ```tsx
117
+ const config: OnboardingConfig = {
118
+ // ...
119
+ style: {
120
+ // The mask overlaying the page
121
+ background: { backgroundColor: 'rgba(0, 0, 0, 0.85)' },
122
+
123
+ // The main tooltip container
124
+ container: {
125
+ borderRadius: '16px',
126
+ boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)'
127
+ },
128
+
129
+ // Buttons
130
+ next: { backgroundColor: '#4F46E5', color: 'white' },
131
+ prev: { color: '#6B7280' },
132
+ finish: { backgroundColor: '#10B981' },
133
+ start: { backgroundColor: '#4F46E5' }, // Used for the "Next" button on the first step
134
+
135
+ // Layout
136
+ padding: 10, // Add 10px padding around the highlighted element
137
+ },
138
+ // ...
139
+ };
140
+ ```
141
+
142
+ ## API Reference
143
+
144
+ ### `OnboardingConfig`
145
+
146
+ | Property | Type | Description |
147
+ | :--- | :--- | :--- |
148
+ | `metadata` | `OnboardingMetadata` | General settings for the onboarding instance. |
149
+ | `steps` | `OnboardingStep[]` | Array of steps defining the flow. |
150
+ | `style` | `OnboardingStyle` | Optional. Visual styling configuration. |
151
+ | `onOnboardingComplete` | `() => void` | Optional. Callback fired when onboarding finishes. |
152
+
153
+ ### `OnboardingMetadata`
154
+
155
+ | Property | Type | Default | Description |
156
+ | :--- | :--- | :--- | :--- |
157
+ | `name` | `string` | **Required** | Unique name for the onboarding flow. |
158
+ | `nextRouter` | `boolean` | `false` | Enable if using Next.js router. |
159
+ | `draggable` | `boolean` | `false` | Allow the tooltip to be dragged. |
160
+ | `inOrder` | `boolean` | `true` | If `true`, strict step order is enforced. If `false`, matching `urlMatch` activates the step. |
161
+
162
+ ### `OnboardingStep`
163
+
164
+ | Property | Type | Description |
165
+ | :--- | :--- | :--- |
166
+ | `title` | `string` | Title displayed in the tooltip. |
167
+ | `description` | `string` | Description text in the tooltip. |
168
+ | `attribute` | `string` | The `data-onboarding-id` value to target. |
169
+ | `urlMatch` | `string` \| `RegExp` | **Required**. Checks if current URL matches to active this step. Supports `*` wildcards in strings (e.g., `"/user/*"`). <br/>**Note:** `RegExp` objects cannot be passed from Server Components in Next.js. Use string wildcards or define config in a Client Component. |
170
+ | `navigate` | `string` | URL to navigate to when this step is completed (next button clicked). |
171
+ | `click` | `boolean` | If `true`, clicks the element when the step activates. |
172
+ | `subSteps` | `OnboardingSubStep[]` | Nested steps for complex workflows. |
173
+
174
+ ### `OnboardingStyle`
175
+
176
+ All properties (except `padding`) accept `React.CSSProperties` objects.
177
+
178
+ | Property | Type | Description |
179
+ | :--- | :--- | :--- |
180
+ | `background` | `CSSProperties` | Styles for the overlay mask. |
181
+ | `container` | `CSSProperties` | Styles for the tooltip box. |
182
+ | `next` | `CSSProperties` | Styles for the "Next" button. |
183
+ | `prev` | `CSSProperties` | Styles for the "Prev" button. |
184
+ | `finish` | `CSSProperties` | Styles for the "Finish" button. |
185
+ | `start` | `CSSProperties` | Styles for the "Start" button (Step 1 "Next" button). |
186
+ | `padding` | `number` | Padding (in px) around the highlighted element. |
187
+
188
+ ## Hooks
189
+
190
+ ### `useOnboarding()`
191
+
192
+ Access the onboarding state and controls from any component within the provider.
193
+
194
+ ```tsx
195
+ import { useOnboarding } from 'onboard-engine';
196
+
197
+ const MyComponent = () => {
198
+ const {
199
+ // Actions
200
+ nextStep, // Go to the next step
201
+ prevStep, // Go to the previous step
202
+ finish, // End the onboarding flow
203
+ goToStep, // Jump to a specific step (index, subStepIndex?)
204
+
205
+ // State
206
+ state, // The full internal state object
207
+ currentStep,// The current OnboardingStep or OnboardingSubStep object
208
+ isFirstStep,// Boolean: true if on the first step
209
+ isLastStep, // Boolean: true if on the last step
210
+
211
+ // Configuration
212
+ config // The full configuration object
213
+ } = useOnboarding();
214
+
215
+ return (
216
+ <button onClick={nextStep}>Next</button>
217
+ );
218
+ };
219
+ ```
220
+
221
+ ## Contributing
222
+
223
+ Contributions are welcome! Please feel free to submit a Pull Request.
224
+
225
+ ## License
226
+
227
+ ISC © [Forsrobin](https://github.com/Forsrobin)
package/dist/index.css ADDED
@@ -0,0 +1,2 @@
1
+ .onboard-overlay-mask{position:absolute;background-color:#000000b3;pointer-events:auto;transition:all .3s cubic-bezier(.25,.1,.25,1)}.onboard-tooltip{position:absolute;width:300px;background-color:#fff;border-radius:12px;box-shadow:0 25px 50px -12px #00000040;pointer-events:auto;padding:20px;border:1px solid #f3f4f6;z-index:10000;transition:top .3s cubic-bezier(.25,.1,.25,1),left .3s cubic-bezier(.25,.1,.25,1)}.onboard-button-primary{background-color:#000;color:#fff;padding:8px 16px;border-radius:8px;font-weight:600;font-size:14px;transition:all .2s;display:flex;align-items:center;gap:4px}.onboard-button-primary:hover{background-color:#1f2937}.onboard-button-primary:active{transform:scale(.95)}.onboard-button-ghost{color:#4b5563;font-weight:500;font-size:14px;transition:color .2s;display:flex;align-items:center;gap:4px}.onboard-button-ghost:hover{color:#111827}.onboard-button-ghost:disabled{color:#d1d5db;cursor:not-allowed}
2
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".onboard-overlay-mask {\n position: absolute;\n background-color: rgba(0, 0, 0, 0.7);\n pointer-events: auto;\n transition: all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n\n.onboard-tooltip {\n position: absolute;\n width: 300px;\n background-color: white;\n border-radius: 12px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n pointer-events: auto;\n padding: 20px;\n border: 1px solid #f3f4f6;\n z-index: 10000;\n transition: top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);\n}\n\n.onboard-button-primary {\n background-color: black;\n color: white;\n padding: 8px 16px;\n border-radius: 8px;\n font-weight: 600;\n font-size: 14px;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.onboard-button-primary:hover {\n background-color: #1f2937;\n}\n\n.onboard-button-primary:active {\n transform: scale(0.95);\n}\n\n.onboard-button-ghost {\n color: #4b5563;\n font-weight: 500;\n font-size: 14px;\n transition: color 0.2s;\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.onboard-button-ghost:hover {\n color: #111827;\n}\n\n.onboard-button-ghost:disabled {\n color: #d1d5db;\n cursor: not-allowed;\n}\n"],"mappings":"AAAA,CAAC,qBACC,SAAU,SACV,iBAAkB,UAClB,eAAgB,KAChB,WAAY,IAAI,IAAK,aAAa,GAAI,CAAE,EAAG,CAAE,GAAI,CAAE,EACrD,CAEA,CAAC,gBACC,SAAU,SACV,MAAO,MACP,iBAAkB,KAVpB,cAWiB,KACf,WAAY,EAAE,KAAK,KAAK,MAAM,UAC9B,eAAgB,KAblB,QAcW,KACT,OAAQ,IAAI,MAAM,QAClB,QAAS,MACT,WAAY,IAAI,IAAK,aAAa,GAAI,CAAE,EAAG,CAAE,GAAI,CAAE,EAAE,CAAE,KAAK,IAAK,aAAa,GAAI,CAAE,EAAG,CAAE,GAAI,CAAE,EACjG,CAEA,CAAC,uBACC,iBAAkB,KAClB,MAAO,KAtBT,QAuBW,IAAI,KAvBf,cAwBiB,IACf,YAAa,IACb,UAAW,KACX,WAAY,IAAI,IAChB,QAAS,KACT,YAAa,OACb,IAAK,GACP,CAEA,CAbC,sBAasB,OACrB,iBAAkB,OACpB,CAEA,CAjBC,sBAiBsB,QACrB,UAAW,MAAM,IACnB,CAEA,CAAC,qBACC,MAAO,QACP,YAAa,IACb,UAAW,KACX,WAAY,MAAM,IAClB,QAAS,KACT,YAAa,OACb,IAAK,GACP,CAEA,CAVC,oBAUoB,OACnB,MAAO,OACT,CAEA,CAdC,oBAcoB,UACnB,MAAO,QACP,OAAQ,WACV","names":[]}
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+
3
+ interface OnboardingSubStep {
4
+ title: string;
5
+ description: string;
6
+ attribute: string;
7
+ navigate?: string;
8
+ click?: boolean;
9
+ }
10
+ interface OnboardingStep {
11
+ title: string;
12
+ description: string;
13
+ attribute: string;
14
+ urlMatch: string | RegExp;
15
+ navigate?: string;
16
+ subSteps?: OnboardingSubStep[];
17
+ click?: boolean;
18
+ }
19
+ interface OnboardingMetadata {
20
+ name: string;
21
+ nextRouter?: boolean;
22
+ draggable?: boolean;
23
+ inOrder?: boolean;
24
+ }
25
+ interface OnboardingStyle {
26
+ padding?: number;
27
+ background?: React.CSSProperties;
28
+ container?: React.CSSProperties;
29
+ next?: React.CSSProperties;
30
+ prev?: React.CSSProperties;
31
+ start?: React.CSSProperties;
32
+ finish?: React.CSSProperties;
33
+ }
34
+ interface OnboardingConfig {
35
+ metadata: OnboardingMetadata;
36
+ steps: OnboardingStep[];
37
+ style?: OnboardingStyle;
38
+ onOnboardingComplete?: () => void;
39
+ }
40
+ interface OnboardingState {
41
+ currentStepIndex: number;
42
+ currentSubStepIndex: number | null;
43
+ isActive: boolean;
44
+ }
45
+
46
+ interface OnboardingContextType {
47
+ config: OnboardingConfig;
48
+ state: OnboardingState;
49
+ nextStep: () => void;
50
+ prevStep: () => void;
51
+ finish: () => void;
52
+ goToStep: (stepIndex: number, subStepIndex?: number | null) => void;
53
+ currentStep: OnboardingStep | OnboardingSubStep | null;
54
+ isFirstStep: boolean;
55
+ isLastStep: boolean;
56
+ }
57
+ declare const OnboardingProvider: React.FC<{
58
+ config: OnboardingConfig;
59
+ ssr?: boolean;
60
+ children: React.ReactNode;
61
+ }>;
62
+ declare const useOnboarding: () => OnboardingContextType;
63
+
64
+ export { type OnboardingConfig, type OnboardingMetadata, OnboardingProvider, type OnboardingState, type OnboardingStep, type OnboardingStyle, type OnboardingSubStep, useOnboarding };
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+
3
+ interface OnboardingSubStep {
4
+ title: string;
5
+ description: string;
6
+ attribute: string;
7
+ navigate?: string;
8
+ click?: boolean;
9
+ }
10
+ interface OnboardingStep {
11
+ title: string;
12
+ description: string;
13
+ attribute: string;
14
+ urlMatch: string | RegExp;
15
+ navigate?: string;
16
+ subSteps?: OnboardingSubStep[];
17
+ click?: boolean;
18
+ }
19
+ interface OnboardingMetadata {
20
+ name: string;
21
+ nextRouter?: boolean;
22
+ draggable?: boolean;
23
+ inOrder?: boolean;
24
+ }
25
+ interface OnboardingStyle {
26
+ padding?: number;
27
+ background?: React.CSSProperties;
28
+ container?: React.CSSProperties;
29
+ next?: React.CSSProperties;
30
+ prev?: React.CSSProperties;
31
+ start?: React.CSSProperties;
32
+ finish?: React.CSSProperties;
33
+ }
34
+ interface OnboardingConfig {
35
+ metadata: OnboardingMetadata;
36
+ steps: OnboardingStep[];
37
+ style?: OnboardingStyle;
38
+ onOnboardingComplete?: () => void;
39
+ }
40
+ interface OnboardingState {
41
+ currentStepIndex: number;
42
+ currentSubStepIndex: number | null;
43
+ isActive: boolean;
44
+ }
45
+
46
+ interface OnboardingContextType {
47
+ config: OnboardingConfig;
48
+ state: OnboardingState;
49
+ nextStep: () => void;
50
+ prevStep: () => void;
51
+ finish: () => void;
52
+ goToStep: (stepIndex: number, subStepIndex?: number | null) => void;
53
+ currentStep: OnboardingStep | OnboardingSubStep | null;
54
+ isFirstStep: boolean;
55
+ isLastStep: boolean;
56
+ }
57
+ declare const OnboardingProvider: React.FC<{
58
+ config: OnboardingConfig;
59
+ ssr?: boolean;
60
+ children: React.ReactNode;
61
+ }>;
62
+ declare const useOnboarding: () => OnboardingContextType;
63
+
64
+ export { type OnboardingConfig, type OnboardingMetadata, OnboardingProvider, type OnboardingState, type OnboardingStep, type OnboardingStyle, type OnboardingSubStep, useOnboarding };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ "use strict";"use client";var Q=Object.create;var W=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var tt=Object.getPrototypeOf,et=Object.prototype.hasOwnProperty;var nt=(e,s)=>{for(var f in s)W(e,f,{get:s[f],enumerable:!0})},F=(e,s,f,y)=>{if(s&&typeof s=="object"||typeof s=="function")for(let m of Z(s))!et.call(e,m)&&m!==f&&W(e,m,{get:()=>s[m],enumerable:!(y=V(s,m))||y.enumerable});return e};var T=(e,s,f)=>(f=e!=null?Q(tt(e)):{},F(s||!e||!e.__esModule?W(f,"default",{value:e,enumerable:!0}):f,e)),ot=e=>F(W({},"__esModule",{value:!0}),e);var it={};nt(it,{OnboardingProvider:()=>rt,useOnboarding:()=>$});module.exports=ot(it);var l=T(require("react")),B=T(require("js-cookie"));var b=require("react"),X=require("react-dom");var a=require("react/jsx-runtime"),j=()=>{let{config:e,currentStep:s,nextStep:f,prevStep:y,finish:m,isFirstStep:n,isLastStep:p}=$(),[d,v]=(0,b.useState)(null),[H,D]=(0,b.useState)({top:0,left:0}),[C,A]=(0,b.useState)({x:0,y:0}),E=(0,b.useRef)(!1),R=(0,b.useRef)({x:0,y:0}),w=(0,b.useRef)(null);(0,b.useEffect)(()=>{A({x:0,y:0})},[s]);let N=r=>{e.metadata.draggable&&(r.stopPropagation(),r.preventDefault(),E.current=!0,R.current={x:r.clientX-C.x,y:r.clientY-C.y},w.current&&(w.current.style.transition="none",w.current.style.cursor="grabbing"),window.addEventListener("pointermove",I),window.addEventListener("pointerup",t))},I=(0,b.useCallback)(r=>{if(!E.current)return;let g=r.clientX-R.current.x,S=r.clientY-R.current.y;A({x:g,y:S})},[]),t=(0,b.useCallback)(()=>{E.current=!1,w.current&&(w.current.style.transition="top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)",w.current.style.cursor=e.metadata.draggable?"grab":"auto"),window.removeEventListener("pointermove",I),window.removeEventListener("pointerup",t)},[e.metadata.draggable,I]);(0,b.useEffect)(()=>()=>{window.removeEventListener("pointermove",I),window.removeEventListener("pointerup",t)},[I,t]);let c=(0,b.useCallback)(r=>{let z=r.top,x=window.innerHeight-r.bottom,U=r.left,G=window.innerWidth-r.right,P=0,L=0;return x>232?(P=r.bottom+12,L=Math.max(20,Math.min(window.innerWidth-300-20,r.left+r.width/2-300/2))):z>232?(P=r.top-200-12,L=Math.max(20,Math.min(window.innerWidth-300-20,r.left+r.width/2-300/2))):G>332?(P=Math.max(20,Math.min(window.innerHeight-200-20,r.top+r.height/2-200/2)),L=r.right+12):U>332?(P=Math.max(20,Math.min(window.innerHeight-200-20,r.top+r.height/2-200/2)),L=r.left-300-12):(P=window.innerHeight/2-200/2,L=window.innerWidth/2-300/2),{top:P+window.scrollY,left:L+window.scrollX}},[]),i=(0,b.useCallback)(()=>{if(!s)return;let r=document.querySelector(`[data-onboarding-id="${s.attribute}"]`);if(r){let g=r.getBoundingClientRect(),S=e.style?.padding||0,k={top:g.top-S,bottom:g.bottom+S,left:g.left-S,right:g.right+S,width:g.width+S*2,height:g.height+S*2},M={top:k.top+window.scrollY,left:k.left+window.scrollX,width:k.width,height:k.height},z=c(k);v(x=>x&&x.top===M.top&&x.left===M.left&&x.width===M.width&&x.height===M.height?x:M),D(x=>x.top===z.top&&x.left===z.left?x:z)}else v(null)},[s,c,e.style]);if((0,b.useEffect)(()=>{i(),window.addEventListener("resize",i),window.addEventListener("scroll",i);let r=new MutationObserver(i);r.observe(document.body,{childList:!0,subtree:!0,attributes:!0});let g=null;if(typeof ResizeObserver<"u"){g=new ResizeObserver(i),g.observe(document.body);let S=s?.attribute?document.querySelector(`[data-onboarding-id="${s.attribute}"]`):null;S&&g.observe(S)}return()=>{window.removeEventListener("resize",i),window.removeEventListener("scroll",i),r.disconnect(),g&&g.disconnect()}},[i,s?.attribute]),!s||!d)return null;let u={...e.style?.background,transition:"all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"},o=r=>{r.stopPropagation()},h=()=>(0,a.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,a.jsx)("path",{d:"M15 18l-6-6 6-6"})}),J=()=>(0,a.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:(0,a.jsx)("path",{d:"M9 18l6-6-6-6"})}),_=()=>(0,a.jsxs)("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[(0,a.jsx)("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),(0,a.jsx)("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}),K=(0,a.jsxs)("div",{className:"fixed inset-0 z-[999999] pointer-events-none",children:[(0,a.jsx)("div",{style:{height:d.top,...u},className:"onboard-overlay-mask top-0 left-0 w-full pointer-events-auto",onPointerDown:o,onMouseDown:o,onClick:o}),(0,a.jsx)("div",{style:{top:d.top+d.height,height:`calc(100vh - ${d.top+d.height}px)`,...u},className:"onboard-overlay-mask left-0 w-full pointer-events-auto",onPointerDown:o,onMouseDown:o,onClick:o}),(0,a.jsx)("div",{style:{top:d.top,height:d.height,width:d.left,...u},className:"onboard-overlay-mask left-0 pointer-events-auto",onPointerDown:o,onMouseDown:o,onClick:o}),(0,a.jsx)("div",{style:{top:d.top,height:d.height,left:d.left+d.width,width:`calc(100% - ${d.left+d.width}px)`,...u},className:"onboard-overlay-mask pointer-events-auto",onPointerDown:o,onMouseDown:o,onClick:o}),(0,a.jsxs)("div",{ref:w,className:"onboard-tooltip pointer-events-auto",onPointerDown:N,style:{zIndex:1e6,...e.style?.container,top:H.top+C.y,left:H.left+C.x,transition:"top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)",cursor:e.metadata.draggable?"grab":"auto",touchAction:"none"},onMouseDown:o,onClick:o,children:[(0,a.jsxs)("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"8px"},children:[(0,a.jsx)("h3",{style:{margin:0,fontWeight:"bold",color:"#111827",fontSize:"18px",lineHeight:1.2},children:s.title}),(0,a.jsx)("button",{onClick:r=>{r.stopPropagation(),m()},style:{background:"none",border:"none",cursor:"pointer",padding:"4px",color:"#9ca3af"},children:(0,a.jsx)(_,{})})]}),(0,a.jsx)("p",{style:{margin:0,color:"#4b5563",fontSize:"14px",marginBottom:"24px",lineHeight:1.5},children:s.description}),(0,a.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[(0,a.jsxs)("button",{onClick:r=>{r.stopPropagation(),y()},disabled:n,className:"onboard-button-ghost",style:{background:"none",border:"none",cursor:n?"not-allowed":"pointer",...e.style?.prev},children:[(0,a.jsx)(h,{}),"Prev"]}),p?(0,a.jsx)("button",{onClick:r=>{r.stopPropagation(),m()},className:"onboard-button-primary",style:{border:"none",cursor:"pointer",...e.style?.finish},children:"Finish"}):(0,a.jsxs)("button",{onClick:r=>{r.stopPropagation(),f()},className:"onboard-button-primary",style:{border:"none",cursor:"pointer",...n?e.style?.start:{},...n?{}:e.style?.next},children:[n&&e.style?.start?"Start":"Next",!(n&&e.style?.start)&&(0,a.jsx)(J,{})]})]})]})]});return typeof document<"u"?(0,X.createPortal)(K,document.body):null};var O=require("react/jsx-runtime"),q=(0,l.createContext)(void 0),Y="onboarding_state",rt=({config:e,ssr:s=!1,children:f})=>{let[y,m]=(0,l.useState)(!s),[n,p]=(0,l.useState)({currentStepIndex:0,currentSubStepIndex:null,isActive:!0}),d=l.default.useRef(e);(0,l.useEffect)(()=>{d.current=e},[e]);let v=(0,l.useCallback)(t=>{t&&(d.current.metadata.nextRouter,window.location.href=t)},[]);(0,l.useEffect)(()=>{s&&m(!0)},[s]);let H=(t,c)=>{if(t.urlMatch instanceof RegExp)return t.urlMatch.test(c);if(typeof t.urlMatch=="string"&&t.urlMatch.includes("*")){let i=t.urlMatch.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${i}$`).test(c)}return c===t.urlMatch};(0,l.useEffect)(()=>{let t=d.current,c=window.location.pathname,i=-1;t.metadata.inOrder===!1&&(i=t.steps.findIndex(o=>H(o,c)));let u=B.default.get(Y);if(u)try{let o=JSON.parse(u);if(t.metadata.inOrder===!1)i!==-1?o.currentStepIndex===i?p(o):p(h=>({...h,currentStepIndex:i,currentSubStepIndex:null,isActive:!0})):p(h=>({...o,isActive:!1}));else if(p(o),t.metadata.inOrder!==!1){let h=t.steps[o.currentStepIndex];h&&o.isActive&&typeof h.urlMatch=="string"&&window.location.pathname!==h.urlMatch&&v(h.urlMatch)}}catch(o){console.error("Failed to parse onboarding state from cookie",o),i!==-1&&p(h=>({...h,currentStepIndex:i,currentSubStepIndex:null,isActive:!0}))}else if(i!==-1)p(o=>({...o,currentStepIndex:i,currentSubStepIndex:null,isActive:!0}));else if(t.metadata.inOrder===!1)p(o=>({...o,isActive:!1}));else{let o=t.steps[0];o&&typeof o.urlMatch=="string"&&window.location.pathname!==o.urlMatch&&v(o.urlMatch)}},[v]),(0,l.useEffect)(()=>{y&&B.default.set(Y,JSON.stringify(n),{expires:365})},[n,y]);let D=(0,l.useMemo)(()=>{let t=e.steps[n.currentStepIndex];return t?n.currentSubStepIndex!==null&&t.subSteps&&t.subSteps[n.currentSubStepIndex]||t:null},[e.steps,n.currentStepIndex,n.currentSubStepIndex]),C=n.currentStepIndex===0&&n.currentSubStepIndex===null,A=(0,l.useMemo)(()=>{let t=e.steps.length,c=n.currentStepIndex===t-1,i=e.steps[n.currentStepIndex],u=i?.subSteps&&i.subSteps.length>0;return c?u?n.currentSubStepIndex===i.subSteps.length-1:!0:!1},[e.steps,n.currentStepIndex,n.currentSubStepIndex]),E=(0,l.useCallback)(()=>{let t=d.current,c=t.steps[n.currentStepIndex],i=n.currentSubStepIndex!==null&&c.subSteps?c.subSteps[n.currentSubStepIndex]:c;if(i.click){let u=document.querySelector(`[data-onboarding-id="${i.attribute}"]`);u&&u.click()}if(c.subSteps&&(n.currentSubStepIndex===null||n.currentSubStepIndex<c.subSteps.length-1)){let u=n.currentSubStepIndex===null?0:n.currentSubStepIndex+1,o=c.subSteps[u];p(h=>({...h,currentSubStepIndex:u})),o.navigate&&v(o.navigate);return}if(n.currentStepIndex<t.steps.length-1){let u=n.currentStepIndex+1,o=t.steps[u];p({currentStepIndex:u,currentSubStepIndex:null,isActive:!0}),o.navigate&&v(o.navigate)}else p(u=>({...u,isActive:!1})),t.onOnboardingComplete&&t.onOnboardingComplete()},[n.currentStepIndex,n.currentSubStepIndex,v]),R=(0,l.useCallback)(()=>{let t=d.current,c=t.steps[n.currentStepIndex];if(n.currentSubStepIndex!==null&&n.currentSubStepIndex>0){p(i=>({...i,currentSubStepIndex:i.currentSubStepIndex-1}));return}if(n.currentSubStepIndex===0){p(i=>({...i,currentSubStepIndex:null}));return}if(n.currentStepIndex>0){let i=n.currentStepIndex-1,u=t.steps[i],o=u.subSteps?u.subSteps.length-1:null;p({currentStepIndex:i,currentSubStepIndex:o,isActive:!0})}},[n.currentStepIndex,n.currentSubStepIndex]),w=(0,l.useCallback)(()=>{p(t=>({...t,isActive:!1})),d.current.onOnboardingComplete&&d.current.onOnboardingComplete()},[]),N=(0,l.useCallback)((t,c=null)=>{p({currentStepIndex:t,currentSubStepIndex:c,isActive:!0})},[]),I={config:e,state:n,nextStep:E,prevStep:R,finish:w,goToStep:N,currentStep:D,isFirstStep:C,isLastStep:A};return y?(0,O.jsxs)(q.Provider,{value:I,children:[f,n.isActive&&(0,O.jsx)(j,{})]}):(0,O.jsx)(O.Fragment,{children:f})},$=()=>{let e=(0,l.useContext)(q);if(e===void 0)throw new Error("useOnboarding must be used within an OnboardingProvider");return e};0&&(module.exports={OnboardingProvider,useOnboarding});
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/components/OnboardingProvider.tsx","../src/components/OnboardingOverlay.tsx"],"sourcesContent":["\"use client\";\n\nimport './styles.css';\nexport * from './components/OnboardingProvider';\nexport * from './types';\n","\"use client\";\n\nimport React, { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport Cookies from 'js-cookie';\nimport { OnboardingConfig, OnboardingState, OnboardingStep, OnboardingSubStep } from '../types';\nimport { OnboardingOverlay } from './OnboardingOverlay';\n\ninterface OnboardingContextType {\n config: OnboardingConfig;\n state: OnboardingState;\n nextStep: () => void;\n prevStep: () => void;\n finish: () => void;\n goToStep: (stepIndex: number, subStepIndex?: number | null) => void;\n currentStep: OnboardingStep | OnboardingSubStep | null;\n isFirstStep: boolean;\n isLastStep: boolean;\n}\n\nconst OnboardingContext = createContext<OnboardingContextType | undefined>(undefined);\n\nconst COOKIE_NAME = 'onboarding_state';\n\nexport const OnboardingProvider: React.FC<{\n config: OnboardingConfig;\n ssr?: boolean;\n children: React.ReactNode;\n}> = ({ config, ssr = false, children }) => {\n const [isMounted, setIsMounted] = useState(!ssr);\n const [state, setState] = useState<OnboardingState>({\n currentStepIndex: 0,\n currentSubStepIndex: null,\n isActive: true,\n });\n\n // Stabilize config to prevent infinite loops if the user passes a new object on every render\n const configRef = React.useRef(config);\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n const handleNavigation = useCallback((link?: string) => {\n if (!link) return;\n \n if (configRef.current.metadata.nextRouter) {\n window.location.href = link;\n } else {\n window.location.href = link;\n }\n }, []);\n\n useEffect(() => {\n if (ssr) {\n setIsMounted(true);\n }\n }, [ssr]);\n\n const isMatch = (step: OnboardingStep, path: string) => {\n if (step.urlMatch instanceof RegExp) return step.urlMatch.test(path);\n \n if (typeof step.urlMatch === 'string' && step.urlMatch.includes('*')) {\n // Escape regex special characters but keep '*' as '.*'\n const pattern = step.urlMatch\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex chars\n .replace(/\\*/g, '.*'); // Convert * to .*\n return new RegExp(`^${pattern}$`).test(path);\n }\n\n return path === step.urlMatch;\n };\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const currentPath = window.location.pathname;\n let matchedStepIndex = -1;\n \n // Check if inOrder is explicitly false to find matching step from URL\n if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n matchedStepIndex = currentConfig.steps.findIndex(step => isMatch(step, currentPath));\n }\n\n const savedState = Cookies.get(COOKIE_NAME);\n if (savedState) {\n try {\n const parsed: OnboardingState = JSON.parse(savedState);\n \n // If inOrder is false\n if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n if (matchedStepIndex !== -1) {\n // We found a matching step for this URL\n if (parsed.currentStepIndex === matchedStepIndex) {\n // If it matches the saved step, restore state (keep substeps)\n setState(parsed);\n } else {\n // Different step, switch to it\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n }\n } else {\n // inOrder is false, and NO step matches this URL.\n // We should hide the onboarding, essentially \"pausing\" it until we return to a valid page.\n setState(prev => ({ ...parsed, isActive: false }));\n }\n } else {\n // Standard behavior (inOrder: true OR no match found) - restore saved state\n setState(parsed);\n\n // Only enforce navigation if inOrder is true (or default)\n if ((currentConfig.metadata.inOrder as boolean | undefined) !== false) {\n const step = currentConfig.steps[parsed.currentStepIndex];\n if (step && parsed.isActive) {\n // Always enforce location based on the main step's urlMatch\n if (typeof step.urlMatch === 'string' && window.location.pathname !== step.urlMatch) {\n handleNavigation(step.urlMatch);\n }\n }\n }\n }\n } catch (e) {\n console.error('Failed to parse onboarding state from cookie', e);\n // Fallback if cookie fails but we have a match\n if (matchedStepIndex !== -1) {\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n }\n }\n } else if (matchedStepIndex !== -1) {\n // No cookie, but we have a URL match\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n } else if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n // No cookie, no match, and inOrder is false.\n // We are on a page that doesn't trigger any onboarding step.\n setState(prev => ({ ...prev, isActive: false }));\n } else {\n // No cookie, no match, inOrder is true (default).\n // Enforce navigation for the default first step if needed.\n const step = currentConfig.steps[0];\n if (step && typeof step.urlMatch === 'string' && window.location.pathname !== step.urlMatch) {\n handleNavigation(step.urlMatch);\n }\n }\n }, [handleNavigation]); // Removed config.steps dependency\n\n useEffect(() => {\n if (isMounted) {\n Cookies.set(COOKIE_NAME, JSON.stringify(state), { expires: 365 });\n }\n }, [state, isMounted]);\n\n const currentStep = useMemo(() => {\n const step = config.steps[state.currentStepIndex];\n if (!step) return null;\n if (state.currentSubStepIndex !== null && step.subSteps) {\n return step.subSteps[state.currentSubStepIndex] || step;\n }\n return step;\n }, [config.steps, state.currentStepIndex, state.currentSubStepIndex]);\n\n const isFirstStep = state.currentStepIndex === 0 && state.currentSubStepIndex === null;\n const isLastStep = useMemo(() => {\n const totalSteps = config.steps.length;\n const isLastMainStep = state.currentStepIndex === totalSteps - 1;\n const step = config.steps[state.currentStepIndex];\n const hasSubSteps = step?.subSteps && step.subSteps.length > 0;\n \n if (isLastMainStep) {\n if (hasSubSteps) {\n return state.currentSubStepIndex === (step.subSteps!.length - 1);\n }\n return true;\n }\n return false;\n }, [config.steps, state.currentStepIndex, state.currentSubStepIndex]);\n\n const nextStep = useCallback(() => {\n const currentConfig = configRef.current;\n const step = currentConfig.steps[state.currentStepIndex];\n const currentActiveStep = state.currentSubStepIndex !== null && step.subSteps \n ? step.subSteps[state.currentSubStepIndex] \n : step;\n\n // Perform click if requested for the current step before moving to the next\n if (currentActiveStep.click) {\n const element = document.querySelector(`[data-onboarding-id=\"${currentActiveStep.attribute}\"]`) as HTMLElement;\n if (element) {\n element.click();\n }\n }\n \n // Check for subSteps\n if (step.subSteps && (state.currentSubStepIndex === null || state.currentSubStepIndex < step.subSteps.length - 1)) {\n const nextSubIndex = state.currentSubStepIndex === null ? 0 : state.currentSubStepIndex + 1;\n const nextSubStep = step.subSteps[nextSubIndex];\n setState(prev => ({ ...prev, currentSubStepIndex: nextSubIndex }));\n \n if (nextSubStep.navigate) handleNavigation(nextSubStep.navigate);\n return;\n }\n\n // Move to next main step\n if (state.currentStepIndex < currentConfig.steps.length - 1) {\n const nextIndex = state.currentStepIndex + 1;\n const nextStepObj = currentConfig.steps[nextIndex];\n setState({\n currentStepIndex: nextIndex,\n currentSubStepIndex: null,\n isActive: true,\n });\n \n if (nextStepObj.navigate) handleNavigation(nextStepObj.navigate);\n } else {\n setState(prev => ({ ...prev, isActive: false }));\n if (currentConfig.onOnboardingComplete) {\n currentConfig.onOnboardingComplete();\n }\n }\n }, [state.currentStepIndex, state.currentSubStepIndex, handleNavigation]);\n\n const prevStep = useCallback(() => {\n const currentConfig = configRef.current;\n const step = currentConfig.steps[state.currentStepIndex];\n\n if (state.currentSubStepIndex !== null && state.currentSubStepIndex > 0) {\n setState(prev => ({ ...prev, currentSubStepIndex: prev.currentSubStepIndex! - 1 }));\n return;\n }\n\n if (state.currentSubStepIndex === 0) {\n setState(prev => ({ ...prev, currentSubStepIndex: null }));\n return;\n }\n\n if (state.currentStepIndex > 0) {\n const prevIndex = state.currentStepIndex - 1;\n const prevStepObj = currentConfig.steps[prevIndex];\n const prevSubStepIndex = prevStepObj.subSteps ? prevStepObj.subSteps.length - 1 : null;\n \n setState({\n currentStepIndex: prevIndex,\n currentSubStepIndex: prevSubStepIndex,\n isActive: true,\n });\n }\n }, [state.currentStepIndex, state.currentSubStepIndex]);\n\n const finish = useCallback(() => {\n setState(prev => ({ ...prev, isActive: false }));\n if (configRef.current.onOnboardingComplete) {\n configRef.current.onOnboardingComplete();\n }\n }, []);\n\n const goToStep = useCallback((stepIndex: number, subStepIndex: number | null = null) => {\n setState({\n currentStepIndex: stepIndex,\n currentSubStepIndex: subStepIndex,\n isActive: true,\n });\n }, []);\n\n const value = {\n config,\n state,\n nextStep,\n prevStep,\n finish,\n goToStep,\n currentStep,\n isFirstStep,\n isLastStep,\n };\n\n if (!isMounted) return <>{children}</>;\n\n return (\n <OnboardingContext.Provider value={value}>\n {children}\n {state.isActive && <OnboardingOverlay />}\n </OnboardingContext.Provider>\n );\n};\n\nexport const useOnboarding = () => {\n const context = useContext(OnboardingContext);\n if (context === undefined) {\n throw new Error('useOnboarding must be used within an OnboardingProvider');\n }\n return context;\n};","\"use client\";\n\nimport React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useOnboarding } from './OnboardingProvider';\n\nexport const OnboardingOverlay: React.FC = () => {\n const { config, currentStep, nextStep, prevStep, finish, isFirstStep, isLastStep } = useOnboarding();\n const [coords, setCoords] = useState<{ top: number; left: number; width: number; height: number } | null>(null);\n const [position, setPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 });\n const [dragOffset, setDragOffset] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const isDragging = useRef(false);\n const dragStart = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n const tooltipRef = useRef<HTMLDivElement>(null);\n\n // Reset drag offset when step changes\n useEffect(() => {\n setDragOffset({ x: 0, y: 0 });\n }, [currentStep]);\n\n const handlePointerDown = (e: React.PointerEvent) => {\n if (!config.metadata.draggable) return;\n e.stopPropagation(); // Prevent click-through\n e.preventDefault(); // Prevent text selection\n isDragging.current = true;\n dragStart.current = { x: e.clientX - dragOffset.x, y: e.clientY - dragOffset.y };\n \n // Disable transition during drag for responsiveness\n if (tooltipRef.current) {\n tooltipRef.current.style.transition = 'none';\n tooltipRef.current.style.cursor = 'grabbing';\n }\n\n window.addEventListener('pointermove', handlePointerMove);\n window.addEventListener('pointerup', handlePointerUp);\n };\n\n const handlePointerMove = useCallback((e: PointerEvent) => {\n if (!isDragging.current) return;\n \n const newX = e.clientX - dragStart.current.x;\n const newY = e.clientY - dragStart.current.y;\n \n setDragOffset({ x: newX, y: newY });\n }, []);\n\n const handlePointerUp = useCallback(() => {\n isDragging.current = false;\n \n // Re-enable transition\n if (tooltipRef.current) {\n tooltipRef.current.style.transition = 'top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)';\n tooltipRef.current.style.cursor = config.metadata.draggable ? 'grab' : 'auto';\n }\n\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerUp);\n }, [config.metadata.draggable, handlePointerMove]);\n\n // Clean up listeners on unmount\n useEffect(() => {\n return () => {\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerUp);\n };\n }, [handlePointerMove, handlePointerUp]);\n\n const calculateBestPosition = useCallback((rect: { top: number; bottom: number; left: number; right: number; width: number; height: number }) => {\n const tooltipWidth = 300;\n const tooltipHeight = 200;\n const gap = 12;\n const padding = 20;\n\n const spaceAbove = rect.top;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceLeft = rect.left;\n const spaceRight = window.innerWidth - rect.right;\n\n let top = 0;\n let left = 0;\n\n if (spaceBelow > tooltipHeight + gap + padding) {\n top = rect.bottom + gap;\n left = Math.max(padding, Math.min(window.innerWidth - tooltipWidth - padding, rect.left + rect.width / 2 - tooltipWidth / 2));\n } else if (spaceAbove > tooltipHeight + gap + padding) {\n top = rect.top - tooltipHeight - gap;\n left = Math.max(padding, Math.min(window.innerWidth - tooltipWidth - padding, rect.left + rect.width / 2 - tooltipWidth / 2));\n } else if (spaceRight > tooltipWidth + gap + padding) {\n top = Math.max(padding, Math.min(window.innerHeight - tooltipHeight - padding, rect.top + rect.height / 2 - tooltipHeight / 2));\n left = rect.right + gap;\n } else if (spaceLeft > tooltipWidth + gap + padding) {\n top = Math.max(padding, Math.min(window.innerHeight - tooltipHeight - padding, rect.top + rect.height / 2 - tooltipHeight / 2));\n left = rect.left - tooltipWidth - gap;\n } else {\n top = window.innerHeight / 2 - tooltipHeight / 2;\n left = window.innerWidth / 2 - tooltipWidth / 2;\n }\n\n return { top: top + window.scrollY, left: left + window.scrollX };\n }, []);\n\n const updateCoords = useCallback(() => {\n if (!currentStep) return;\n\n const element = document.querySelector(`[data-onboarding-id=\"${currentStep.attribute}\"]`) as HTMLElement;\n if (element) {\n const rect = element.getBoundingClientRect();\n const padding = config.style?.padding || 0;\n \n const paddedRect = {\n top: rect.top - padding,\n bottom: rect.bottom + padding,\n left: rect.left - padding,\n right: rect.right + padding,\n width: rect.width + (padding * 2),\n height: rect.height + (padding * 2),\n };\n\n const newCoords = {\n top: paddedRect.top + window.scrollY,\n left: paddedRect.left + window.scrollX,\n width: paddedRect.width,\n height: paddedRect.height,\n };\n\n const newPosition = calculateBestPosition(paddedRect);\n\n // Prevent infinite loops by only updating if values actually changed\n setCoords(prev => {\n if (prev && \n prev.top === newCoords.top && \n prev.left === newCoords.left && \n prev.width === newCoords.width && \n prev.height === newCoords.height) {\n return prev;\n }\n return newCoords;\n });\n\n setPosition(prev => {\n if (prev.top === newPosition.top && prev.left === newPosition.left) {\n return prev;\n }\n return newPosition;\n });\n } else {\n setCoords(null);\n }\n }, [currentStep, calculateBestPosition, config.style]);\n\n useEffect(() => {\n updateCoords();\n window.addEventListener('resize', updateCoords);\n window.addEventListener('scroll', updateCoords);\n\n const observer = new MutationObserver(updateCoords);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(updateCoords);\n resizeObserver.observe(document.body);\n \n const element = currentStep?.attribute \n ? document.querySelector(`[data-onboarding-id=\"${currentStep.attribute}\"]`) \n : null;\n if (element) {\n resizeObserver.observe(element);\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateCoords);\n window.removeEventListener('scroll', updateCoords);\n observer.disconnect();\n if (resizeObserver) resizeObserver.disconnect();\n };\n }, [updateCoords, currentStep?.attribute]);\n\n if (!currentStep || !coords) return null;\n\n const maskStyle = {\n ...config.style?.background,\n transition: 'all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)',\n };\n\n const stopPropagation = (e: React.PointerEvent | React.MouseEvent) => {\n e.stopPropagation();\n };\n\n const ChevronLeftIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n\n const ChevronRightIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n\n const XIcon = () => (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n\n const overlayContent = (\n <div className=\"fixed inset-0 z-[999999] pointer-events-none\">\n {/* Top Mask */}\n <div\n style={{ height: coords.top, ...maskStyle }}\n className=\"onboard-overlay-mask top-0 left-0 w-full pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Bottom Mask */}\n <div\n style={{ top: coords.top + coords.height, height: `calc(100vh - ${coords.top + coords.height}px)`, ...maskStyle }}\n className=\"onboard-overlay-mask left-0 w-full pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Left Mask */}\n <div\n style={{ top: coords.top, height: coords.height, width: coords.left, ...maskStyle }}\n className=\"onboard-overlay-mask left-0 pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Right Mask */}\n <div\n style={{ \n top: coords.top, \n height: coords.height, \n left: coords.left + coords.width, \n width: `calc(100% - ${coords.left + coords.width}px)`, \n ...maskStyle \n }}\n className=\"onboard-overlay-mask pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n\n {/* Tooltip */}\n <div\n ref={tooltipRef}\n className=\"onboard-tooltip pointer-events-auto\"\n onPointerDown={handlePointerDown}\n style={{ \n zIndex: 1000000, \n ...config.style?.container,\n top: position.top + dragOffset.y,\n left: position.left + dragOffset.x,\n transition: 'top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)',\n cursor: config.metadata.draggable ? 'grab' : 'auto',\n touchAction: 'none' // Prevent scrolling on touch devices while dragging\n }}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '8px' }}>\n <h3 style={{ margin: 0, fontWeight: 'bold', color: '#111827', fontSize: '18px', lineHeight: 1.2 }}>{currentStep.title}</h3>\n <button \n onClick={(e) => { e.stopPropagation(); finish(); }}\n style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '4px', color: '#9ca3af' }}\n >\n <XIcon />\n </button>\n </div>\n <p style={{ margin: 0, color: '#4b5563', fontSize: '14px', marginBottom: '24px', lineHeight: 1.5 }}>\n {currentStep.description}\n </p>\n \n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <button\n onClick={(e) => { e.stopPropagation(); prevStep(); }}\n disabled={isFirstStep}\n className=\"onboard-button-ghost\"\n style={{ \n background: 'none', \n border: 'none', \n cursor: isFirstStep ? 'not-allowed' : 'pointer',\n ...config.style?.prev \n }}\n >\n <ChevronLeftIcon />\n Prev\n </button>\n \n {isLastStep ? (\n <button\n onClick={(e) => { e.stopPropagation(); finish(); }}\n className=\"onboard-button-primary\"\n style={{ border: 'none', cursor: 'pointer', ...config.style?.finish }}\n >\n Finish\n </button>\n ) : (\n <button\n onClick={(e) => { e.stopPropagation(); nextStep(); }}\n className=\"onboard-button-primary\"\n style={{ \n border: 'none', \n cursor: 'pointer',\n ...(isFirstStep ? config.style?.start : {}),\n ...(!isFirstStep ? config.style?.next : {})\n }}\n >\n {isFirstStep && config.style?.start ? 'Start' : 'Next'}\n {!(isFirstStep && config.style?.start) && <ChevronRightIcon />}\n </button>\n )}\n </div>\n </div>\n </div>\n );\n\n return typeof document !== 'undefined' \n ? createPortal(overlayContent, document.body) \n : null;\n};\n"],"mappings":"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","names":["index_exports","__export","OnboardingProvider","useOnboarding","__toCommonJS","import_react","import_js_cookie","import_react","import_react_dom","import_jsx_runtime","OnboardingOverlay","config","currentStep","nextStep","prevStep","finish","isFirstStep","isLastStep","useOnboarding","coords","setCoords","position","setPosition","dragOffset","setDragOffset","isDragging","dragStart","tooltipRef","handlePointerDown","e","handlePointerMove","handlePointerUp","newX","newY","calculateBestPosition","rect","spaceAbove","spaceBelow","spaceLeft","spaceRight","top","left","updateCoords","element","padding","paddedRect","newCoords","newPosition","prev","observer","resizeObserver","maskStyle","stopPropagation","ChevronLeftIcon","ChevronRightIcon","XIcon","overlayContent","import_jsx_runtime","OnboardingContext","COOKIE_NAME","OnboardingProvider","config","ssr","children","isMounted","setIsMounted","state","setState","configRef","React","handleNavigation","link","isMatch","step","path","pattern","currentConfig","currentPath","matchedStepIndex","savedState","Cookies","parsed","prev","e","currentStep","isFirstStep","isLastStep","totalSteps","isLastMainStep","hasSubSteps","nextStep","currentActiveStep","element","nextSubIndex","nextSubStep","nextIndex","nextStepObj","prevStep","prevIndex","prevStepObj","prevSubStepIndex","finish","goToStep","stepIndex","subStepIndex","value","OnboardingOverlay","useOnboarding","context"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ "use client";import et,{createContext as nt,useContext as ot,useEffect as W,useState as j,useCallback as L,useMemo as Y}from"react";import q from"js-cookie";import{useState as $,useEffect as B,useCallback as A,useRef as F}from"react";import{createPortal as tt}from"react-dom";import{jsx as l,jsxs as m}from"react/jsx-runtime";var T=()=>{let{config:i,currentStep:p,nextStep:E,prevStep:C,finish:R,isFirstStep:e,isLastStep:u}=X(),[s,h]=$(null),[z,D]=$({top:0,left:0}),[v,H]=$({x:0,y:0}),k=F(!1),M=F({x:0,y:0}),S=F(null);B(()=>{H({x:0,y:0})},[p]);let N=o=>{i.metadata.draggable&&(o.stopPropagation(),o.preventDefault(),k.current=!0,M.current={x:o.clientX-v.x,y:o.clientY-v.y},S.current&&(S.current.style.transition="none",S.current.style.cursor="grabbing"),window.addEventListener("pointermove",x),window.addEventListener("pointerup",t))},x=A(o=>{if(!k.current)return;let c=o.clientX-M.current.x,g=o.clientY-M.current.y;H({x:c,y:g})},[]),t=A(()=>{k.current=!1,S.current&&(S.current.style.transition="top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)",S.current.style.cursor=i.metadata.draggable?"grab":"auto"),window.removeEventListener("pointermove",x),window.removeEventListener("pointerup",t)},[i.metadata.draggable,x]);B(()=>()=>{window.removeEventListener("pointermove",x),window.removeEventListener("pointerup",t)},[x,t]);let d=A(o=>{let P=o.top,f=window.innerHeight-o.bottom,V=o.left,Z=window.innerWidth-o.right,I=0,O=0;return f>232?(I=o.bottom+12,O=Math.max(20,Math.min(window.innerWidth-300-20,o.left+o.width/2-300/2))):P>232?(I=o.top-200-12,O=Math.max(20,Math.min(window.innerWidth-300-20,o.left+o.width/2-300/2))):Z>332?(I=Math.max(20,Math.min(window.innerHeight-200-20,o.top+o.height/2-200/2)),O=o.right+12):V>332?(I=Math.max(20,Math.min(window.innerHeight-200-20,o.top+o.height/2-200/2)),O=o.left-300-12):(I=window.innerHeight/2-200/2,O=window.innerWidth/2-300/2),{top:I+window.scrollY,left:O+window.scrollX}},[]),r=A(()=>{if(!p)return;let o=document.querySelector(`[data-onboarding-id="${p.attribute}"]`);if(o){let c=o.getBoundingClientRect(),g=i.style?.padding||0,w={top:c.top-g,bottom:c.bottom+g,left:c.left-g,right:c.right+g,width:c.width+g*2,height:c.height+g*2},y={top:w.top+window.scrollY,left:w.left+window.scrollX,width:w.width,height:w.height},P=d(w);h(f=>f&&f.top===y.top&&f.left===y.left&&f.width===y.width&&f.height===y.height?f:y),D(f=>f.top===P.top&&f.left===P.left?f:P)}else h(null)},[p,d,i.style]);if(B(()=>{r(),window.addEventListener("resize",r),window.addEventListener("scroll",r);let o=new MutationObserver(r);o.observe(document.body,{childList:!0,subtree:!0,attributes:!0});let c=null;if(typeof ResizeObserver<"u"){c=new ResizeObserver(r),c.observe(document.body);let g=p?.attribute?document.querySelector(`[data-onboarding-id="${p.attribute}"]`):null;g&&c.observe(g)}return()=>{window.removeEventListener("resize",r),window.removeEventListener("scroll",r),o.disconnect(),c&&c.disconnect()}},[r,p?.attribute]),!p||!s)return null;let a={...i.style?.background,transition:"all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)"},n=o=>{o.stopPropagation()},b=()=>l("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:l("path",{d:"M15 18l-6-6 6-6"})}),U=()=>l("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:l("path",{d:"M9 18l6-6-6-6"})}),G=()=>m("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[l("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),l("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}),Q=m("div",{className:"fixed inset-0 z-[999999] pointer-events-none",children:[l("div",{style:{height:s.top,...a},className:"onboard-overlay-mask top-0 left-0 w-full pointer-events-auto",onPointerDown:n,onMouseDown:n,onClick:n}),l("div",{style:{top:s.top+s.height,height:`calc(100vh - ${s.top+s.height}px)`,...a},className:"onboard-overlay-mask left-0 w-full pointer-events-auto",onPointerDown:n,onMouseDown:n,onClick:n}),l("div",{style:{top:s.top,height:s.height,width:s.left,...a},className:"onboard-overlay-mask left-0 pointer-events-auto",onPointerDown:n,onMouseDown:n,onClick:n}),l("div",{style:{top:s.top,height:s.height,left:s.left+s.width,width:`calc(100% - ${s.left+s.width}px)`,...a},className:"onboard-overlay-mask pointer-events-auto",onPointerDown:n,onMouseDown:n,onClick:n}),m("div",{ref:S,className:"onboard-tooltip pointer-events-auto",onPointerDown:N,style:{zIndex:1e6,...i.style?.container,top:z.top+v.y,left:z.left+v.x,transition:"top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)",cursor:i.metadata.draggable?"grab":"auto",touchAction:"none"},onMouseDown:n,onClick:n,children:[m("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"8px"},children:[l("h3",{style:{margin:0,fontWeight:"bold",color:"#111827",fontSize:"18px",lineHeight:1.2},children:p.title}),l("button",{onClick:o=>{o.stopPropagation(),R()},style:{background:"none",border:"none",cursor:"pointer",padding:"4px",color:"#9ca3af"},children:l(G,{})})]}),l("p",{style:{margin:0,color:"#4b5563",fontSize:"14px",marginBottom:"24px",lineHeight:1.5},children:p.description}),m("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[m("button",{onClick:o=>{o.stopPropagation(),C()},disabled:e,className:"onboard-button-ghost",style:{background:"none",border:"none",cursor:e?"not-allowed":"pointer",...i.style?.prev},children:[l(b,{}),"Prev"]}),u?l("button",{onClick:o=>{o.stopPropagation(),R()},className:"onboard-button-primary",style:{border:"none",cursor:"pointer",...i.style?.finish},children:"Finish"}):m("button",{onClick:o=>{o.stopPropagation(),E()},className:"onboard-button-primary",style:{border:"none",cursor:"pointer",...e?i.style?.start:{},...e?{}:i.style?.next},children:[e&&i.style?.start?"Start":"Next",!(e&&i.style?.start)&&l(U,{})]})]})]})]});return typeof document<"u"?tt(Q,document.body):null};import{Fragment as rt,jsx as _,jsxs as it}from"react/jsx-runtime";var K=nt(void 0),J="onboarding_state",St=({config:i,ssr:p=!1,children:E})=>{let[C,R]=j(!p),[e,u]=j({currentStepIndex:0,currentSubStepIndex:null,isActive:!0}),s=et.useRef(i);W(()=>{s.current=i},[i]);let h=L(t=>{t&&(s.current.metadata.nextRouter,window.location.href=t)},[]);W(()=>{p&&R(!0)},[p]);let z=(t,d)=>{if(t.urlMatch instanceof RegExp)return t.urlMatch.test(d);if(typeof t.urlMatch=="string"&&t.urlMatch.includes("*")){let r=t.urlMatch.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`).test(d)}return d===t.urlMatch};W(()=>{let t=s.current,d=window.location.pathname,r=-1;t.metadata.inOrder===!1&&(r=t.steps.findIndex(n=>z(n,d)));let a=q.get(J);if(a)try{let n=JSON.parse(a);if(t.metadata.inOrder===!1)r!==-1?n.currentStepIndex===r?u(n):u(b=>({...b,currentStepIndex:r,currentSubStepIndex:null,isActive:!0})):u(b=>({...n,isActive:!1}));else if(u(n),t.metadata.inOrder!==!1){let b=t.steps[n.currentStepIndex];b&&n.isActive&&typeof b.urlMatch=="string"&&window.location.pathname!==b.urlMatch&&h(b.urlMatch)}}catch(n){console.error("Failed to parse onboarding state from cookie",n),r!==-1&&u(b=>({...b,currentStepIndex:r,currentSubStepIndex:null,isActive:!0}))}else if(r!==-1)u(n=>({...n,currentStepIndex:r,currentSubStepIndex:null,isActive:!0}));else if(t.metadata.inOrder===!1)u(n=>({...n,isActive:!1}));else{let n=t.steps[0];n&&typeof n.urlMatch=="string"&&window.location.pathname!==n.urlMatch&&h(n.urlMatch)}},[h]),W(()=>{C&&q.set(J,JSON.stringify(e),{expires:365})},[e,C]);let D=Y(()=>{let t=i.steps[e.currentStepIndex];return t?e.currentSubStepIndex!==null&&t.subSteps&&t.subSteps[e.currentSubStepIndex]||t:null},[i.steps,e.currentStepIndex,e.currentSubStepIndex]),v=e.currentStepIndex===0&&e.currentSubStepIndex===null,H=Y(()=>{let t=i.steps.length,d=e.currentStepIndex===t-1,r=i.steps[e.currentStepIndex],a=r?.subSteps&&r.subSteps.length>0;return d?a?e.currentSubStepIndex===r.subSteps.length-1:!0:!1},[i.steps,e.currentStepIndex,e.currentSubStepIndex]),k=L(()=>{let t=s.current,d=t.steps[e.currentStepIndex],r=e.currentSubStepIndex!==null&&d.subSteps?d.subSteps[e.currentSubStepIndex]:d;if(r.click){let a=document.querySelector(`[data-onboarding-id="${r.attribute}"]`);a&&a.click()}if(d.subSteps&&(e.currentSubStepIndex===null||e.currentSubStepIndex<d.subSteps.length-1)){let a=e.currentSubStepIndex===null?0:e.currentSubStepIndex+1,n=d.subSteps[a];u(b=>({...b,currentSubStepIndex:a})),n.navigate&&h(n.navigate);return}if(e.currentStepIndex<t.steps.length-1){let a=e.currentStepIndex+1,n=t.steps[a];u({currentStepIndex:a,currentSubStepIndex:null,isActive:!0}),n.navigate&&h(n.navigate)}else u(a=>({...a,isActive:!1})),t.onOnboardingComplete&&t.onOnboardingComplete()},[e.currentStepIndex,e.currentSubStepIndex,h]),M=L(()=>{let t=s.current,d=t.steps[e.currentStepIndex];if(e.currentSubStepIndex!==null&&e.currentSubStepIndex>0){u(r=>({...r,currentSubStepIndex:r.currentSubStepIndex-1}));return}if(e.currentSubStepIndex===0){u(r=>({...r,currentSubStepIndex:null}));return}if(e.currentStepIndex>0){let r=e.currentStepIndex-1,a=t.steps[r],n=a.subSteps?a.subSteps.length-1:null;u({currentStepIndex:r,currentSubStepIndex:n,isActive:!0})}},[e.currentStepIndex,e.currentSubStepIndex]),S=L(()=>{u(t=>({...t,isActive:!1})),s.current.onOnboardingComplete&&s.current.onOnboardingComplete()},[]),N=L((t,d=null)=>{u({currentStepIndex:t,currentSubStepIndex:d,isActive:!0})},[]),x={config:i,state:e,nextStep:k,prevStep:M,finish:S,goToStep:N,currentStep:D,isFirstStep:v,isLastStep:H};return C?it(K.Provider,{value:x,children:[E,e.isActive&&_(T,{})]}):_(rt,{children:E})},X=()=>{let i=ot(K);if(i===void 0)throw new Error("useOnboarding must be used within an OnboardingProvider");return i};export{St as OnboardingProvider,X as useOnboarding};
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/OnboardingProvider.tsx","../src/components/OnboardingOverlay.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useEffect, useState, useCallback, useMemo } from 'react';\nimport Cookies from 'js-cookie';\nimport { OnboardingConfig, OnboardingState, OnboardingStep, OnboardingSubStep } from '../types';\nimport { OnboardingOverlay } from './OnboardingOverlay';\n\ninterface OnboardingContextType {\n config: OnboardingConfig;\n state: OnboardingState;\n nextStep: () => void;\n prevStep: () => void;\n finish: () => void;\n goToStep: (stepIndex: number, subStepIndex?: number | null) => void;\n currentStep: OnboardingStep | OnboardingSubStep | null;\n isFirstStep: boolean;\n isLastStep: boolean;\n}\n\nconst OnboardingContext = createContext<OnboardingContextType | undefined>(undefined);\n\nconst COOKIE_NAME = 'onboarding_state';\n\nexport const OnboardingProvider: React.FC<{\n config: OnboardingConfig;\n ssr?: boolean;\n children: React.ReactNode;\n}> = ({ config, ssr = false, children }) => {\n const [isMounted, setIsMounted] = useState(!ssr);\n const [state, setState] = useState<OnboardingState>({\n currentStepIndex: 0,\n currentSubStepIndex: null,\n isActive: true,\n });\n\n // Stabilize config to prevent infinite loops if the user passes a new object on every render\n const configRef = React.useRef(config);\n useEffect(() => {\n configRef.current = config;\n }, [config]);\n\n const handleNavigation = useCallback((link?: string) => {\n if (!link) return;\n \n if (configRef.current.metadata.nextRouter) {\n window.location.href = link;\n } else {\n window.location.href = link;\n }\n }, []);\n\n useEffect(() => {\n if (ssr) {\n setIsMounted(true);\n }\n }, [ssr]);\n\n const isMatch = (step: OnboardingStep, path: string) => {\n if (step.urlMatch instanceof RegExp) return step.urlMatch.test(path);\n \n if (typeof step.urlMatch === 'string' && step.urlMatch.includes('*')) {\n // Escape regex special characters but keep '*' as '.*'\n const pattern = step.urlMatch\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex chars\n .replace(/\\*/g, '.*'); // Convert * to .*\n return new RegExp(`^${pattern}$`).test(path);\n }\n\n return path === step.urlMatch;\n };\n\n useEffect(() => {\n const currentConfig = configRef.current;\n const currentPath = window.location.pathname;\n let matchedStepIndex = -1;\n \n // Check if inOrder is explicitly false to find matching step from URL\n if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n matchedStepIndex = currentConfig.steps.findIndex(step => isMatch(step, currentPath));\n }\n\n const savedState = Cookies.get(COOKIE_NAME);\n if (savedState) {\n try {\n const parsed: OnboardingState = JSON.parse(savedState);\n \n // If inOrder is false\n if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n if (matchedStepIndex !== -1) {\n // We found a matching step for this URL\n if (parsed.currentStepIndex === matchedStepIndex) {\n // If it matches the saved step, restore state (keep substeps)\n setState(parsed);\n } else {\n // Different step, switch to it\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n }\n } else {\n // inOrder is false, and NO step matches this URL.\n // We should hide the onboarding, essentially \"pausing\" it until we return to a valid page.\n setState(prev => ({ ...parsed, isActive: false }));\n }\n } else {\n // Standard behavior (inOrder: true OR no match found) - restore saved state\n setState(parsed);\n\n // Only enforce navigation if inOrder is true (or default)\n if ((currentConfig.metadata.inOrder as boolean | undefined) !== false) {\n const step = currentConfig.steps[parsed.currentStepIndex];\n if (step && parsed.isActive) {\n // Always enforce location based on the main step's urlMatch\n if (typeof step.urlMatch === 'string' && window.location.pathname !== step.urlMatch) {\n handleNavigation(step.urlMatch);\n }\n }\n }\n }\n } catch (e) {\n console.error('Failed to parse onboarding state from cookie', e);\n // Fallback if cookie fails but we have a match\n if (matchedStepIndex !== -1) {\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n }\n }\n } else if (matchedStepIndex !== -1) {\n // No cookie, but we have a URL match\n setState(prev => ({\n ...prev,\n currentStepIndex: matchedStepIndex,\n currentSubStepIndex: null,\n isActive: true\n }));\n } else if ((currentConfig.metadata.inOrder as boolean | undefined) === false) {\n // No cookie, no match, and inOrder is false.\n // We are on a page that doesn't trigger any onboarding step.\n setState(prev => ({ ...prev, isActive: false }));\n } else {\n // No cookie, no match, inOrder is true (default).\n // Enforce navigation for the default first step if needed.\n const step = currentConfig.steps[0];\n if (step && typeof step.urlMatch === 'string' && window.location.pathname !== step.urlMatch) {\n handleNavigation(step.urlMatch);\n }\n }\n }, [handleNavigation]); // Removed config.steps dependency\n\n useEffect(() => {\n if (isMounted) {\n Cookies.set(COOKIE_NAME, JSON.stringify(state), { expires: 365 });\n }\n }, [state, isMounted]);\n\n const currentStep = useMemo(() => {\n const step = config.steps[state.currentStepIndex];\n if (!step) return null;\n if (state.currentSubStepIndex !== null && step.subSteps) {\n return step.subSteps[state.currentSubStepIndex] || step;\n }\n return step;\n }, [config.steps, state.currentStepIndex, state.currentSubStepIndex]);\n\n const isFirstStep = state.currentStepIndex === 0 && state.currentSubStepIndex === null;\n const isLastStep = useMemo(() => {\n const totalSteps = config.steps.length;\n const isLastMainStep = state.currentStepIndex === totalSteps - 1;\n const step = config.steps[state.currentStepIndex];\n const hasSubSteps = step?.subSteps && step.subSteps.length > 0;\n \n if (isLastMainStep) {\n if (hasSubSteps) {\n return state.currentSubStepIndex === (step.subSteps!.length - 1);\n }\n return true;\n }\n return false;\n }, [config.steps, state.currentStepIndex, state.currentSubStepIndex]);\n\n const nextStep = useCallback(() => {\n const currentConfig = configRef.current;\n const step = currentConfig.steps[state.currentStepIndex];\n const currentActiveStep = state.currentSubStepIndex !== null && step.subSteps \n ? step.subSteps[state.currentSubStepIndex] \n : step;\n\n // Perform click if requested for the current step before moving to the next\n if (currentActiveStep.click) {\n const element = document.querySelector(`[data-onboarding-id=\"${currentActiveStep.attribute}\"]`) as HTMLElement;\n if (element) {\n element.click();\n }\n }\n \n // Check for subSteps\n if (step.subSteps && (state.currentSubStepIndex === null || state.currentSubStepIndex < step.subSteps.length - 1)) {\n const nextSubIndex = state.currentSubStepIndex === null ? 0 : state.currentSubStepIndex + 1;\n const nextSubStep = step.subSteps[nextSubIndex];\n setState(prev => ({ ...prev, currentSubStepIndex: nextSubIndex }));\n \n if (nextSubStep.navigate) handleNavigation(nextSubStep.navigate);\n return;\n }\n\n // Move to next main step\n if (state.currentStepIndex < currentConfig.steps.length - 1) {\n const nextIndex = state.currentStepIndex + 1;\n const nextStepObj = currentConfig.steps[nextIndex];\n setState({\n currentStepIndex: nextIndex,\n currentSubStepIndex: null,\n isActive: true,\n });\n \n if (nextStepObj.navigate) handleNavigation(nextStepObj.navigate);\n } else {\n setState(prev => ({ ...prev, isActive: false }));\n if (currentConfig.onOnboardingComplete) {\n currentConfig.onOnboardingComplete();\n }\n }\n }, [state.currentStepIndex, state.currentSubStepIndex, handleNavigation]);\n\n const prevStep = useCallback(() => {\n const currentConfig = configRef.current;\n const step = currentConfig.steps[state.currentStepIndex];\n\n if (state.currentSubStepIndex !== null && state.currentSubStepIndex > 0) {\n setState(prev => ({ ...prev, currentSubStepIndex: prev.currentSubStepIndex! - 1 }));\n return;\n }\n\n if (state.currentSubStepIndex === 0) {\n setState(prev => ({ ...prev, currentSubStepIndex: null }));\n return;\n }\n\n if (state.currentStepIndex > 0) {\n const prevIndex = state.currentStepIndex - 1;\n const prevStepObj = currentConfig.steps[prevIndex];\n const prevSubStepIndex = prevStepObj.subSteps ? prevStepObj.subSteps.length - 1 : null;\n \n setState({\n currentStepIndex: prevIndex,\n currentSubStepIndex: prevSubStepIndex,\n isActive: true,\n });\n }\n }, [state.currentStepIndex, state.currentSubStepIndex]);\n\n const finish = useCallback(() => {\n setState(prev => ({ ...prev, isActive: false }));\n if (configRef.current.onOnboardingComplete) {\n configRef.current.onOnboardingComplete();\n }\n }, []);\n\n const goToStep = useCallback((stepIndex: number, subStepIndex: number | null = null) => {\n setState({\n currentStepIndex: stepIndex,\n currentSubStepIndex: subStepIndex,\n isActive: true,\n });\n }, []);\n\n const value = {\n config,\n state,\n nextStep,\n prevStep,\n finish,\n goToStep,\n currentStep,\n isFirstStep,\n isLastStep,\n };\n\n if (!isMounted) return <>{children}</>;\n\n return (\n <OnboardingContext.Provider value={value}>\n {children}\n {state.isActive && <OnboardingOverlay />}\n </OnboardingContext.Provider>\n );\n};\n\nexport const useOnboarding = () => {\n const context = useContext(OnboardingContext);\n if (context === undefined) {\n throw new Error('useOnboarding must be used within an OnboardingProvider');\n }\n return context;\n};","\"use client\";\n\nimport React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useOnboarding } from './OnboardingProvider';\n\nexport const OnboardingOverlay: React.FC = () => {\n const { config, currentStep, nextStep, prevStep, finish, isFirstStep, isLastStep } = useOnboarding();\n const [coords, setCoords] = useState<{ top: number; left: number; width: number; height: number } | null>(null);\n const [position, setPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 });\n const [dragOffset, setDragOffset] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const isDragging = useRef(false);\n const dragStart = useRef<{ x: number; y: number }>({ x: 0, y: 0 });\n const tooltipRef = useRef<HTMLDivElement>(null);\n\n // Reset drag offset when step changes\n useEffect(() => {\n setDragOffset({ x: 0, y: 0 });\n }, [currentStep]);\n\n const handlePointerDown = (e: React.PointerEvent) => {\n if (!config.metadata.draggable) return;\n e.stopPropagation(); // Prevent click-through\n e.preventDefault(); // Prevent text selection\n isDragging.current = true;\n dragStart.current = { x: e.clientX - dragOffset.x, y: e.clientY - dragOffset.y };\n \n // Disable transition during drag for responsiveness\n if (tooltipRef.current) {\n tooltipRef.current.style.transition = 'none';\n tooltipRef.current.style.cursor = 'grabbing';\n }\n\n window.addEventListener('pointermove', handlePointerMove);\n window.addEventListener('pointerup', handlePointerUp);\n };\n\n const handlePointerMove = useCallback((e: PointerEvent) => {\n if (!isDragging.current) return;\n \n const newX = e.clientX - dragStart.current.x;\n const newY = e.clientY - dragStart.current.y;\n \n setDragOffset({ x: newX, y: newY });\n }, []);\n\n const handlePointerUp = useCallback(() => {\n isDragging.current = false;\n \n // Re-enable transition\n if (tooltipRef.current) {\n tooltipRef.current.style.transition = 'top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)';\n tooltipRef.current.style.cursor = config.metadata.draggable ? 'grab' : 'auto';\n }\n\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerUp);\n }, [config.metadata.draggable, handlePointerMove]);\n\n // Clean up listeners on unmount\n useEffect(() => {\n return () => {\n window.removeEventListener('pointermove', handlePointerMove);\n window.removeEventListener('pointerup', handlePointerUp);\n };\n }, [handlePointerMove, handlePointerUp]);\n\n const calculateBestPosition = useCallback((rect: { top: number; bottom: number; left: number; right: number; width: number; height: number }) => {\n const tooltipWidth = 300;\n const tooltipHeight = 200;\n const gap = 12;\n const padding = 20;\n\n const spaceAbove = rect.top;\n const spaceBelow = window.innerHeight - rect.bottom;\n const spaceLeft = rect.left;\n const spaceRight = window.innerWidth - rect.right;\n\n let top = 0;\n let left = 0;\n\n if (spaceBelow > tooltipHeight + gap + padding) {\n top = rect.bottom + gap;\n left = Math.max(padding, Math.min(window.innerWidth - tooltipWidth - padding, rect.left + rect.width / 2 - tooltipWidth / 2));\n } else if (spaceAbove > tooltipHeight + gap + padding) {\n top = rect.top - tooltipHeight - gap;\n left = Math.max(padding, Math.min(window.innerWidth - tooltipWidth - padding, rect.left + rect.width / 2 - tooltipWidth / 2));\n } else if (spaceRight > tooltipWidth + gap + padding) {\n top = Math.max(padding, Math.min(window.innerHeight - tooltipHeight - padding, rect.top + rect.height / 2 - tooltipHeight / 2));\n left = rect.right + gap;\n } else if (spaceLeft > tooltipWidth + gap + padding) {\n top = Math.max(padding, Math.min(window.innerHeight - tooltipHeight - padding, rect.top + rect.height / 2 - tooltipHeight / 2));\n left = rect.left - tooltipWidth - gap;\n } else {\n top = window.innerHeight / 2 - tooltipHeight / 2;\n left = window.innerWidth / 2 - tooltipWidth / 2;\n }\n\n return { top: top + window.scrollY, left: left + window.scrollX };\n }, []);\n\n const updateCoords = useCallback(() => {\n if (!currentStep) return;\n\n const element = document.querySelector(`[data-onboarding-id=\"${currentStep.attribute}\"]`) as HTMLElement;\n if (element) {\n const rect = element.getBoundingClientRect();\n const padding = config.style?.padding || 0;\n \n const paddedRect = {\n top: rect.top - padding,\n bottom: rect.bottom + padding,\n left: rect.left - padding,\n right: rect.right + padding,\n width: rect.width + (padding * 2),\n height: rect.height + (padding * 2),\n };\n\n const newCoords = {\n top: paddedRect.top + window.scrollY,\n left: paddedRect.left + window.scrollX,\n width: paddedRect.width,\n height: paddedRect.height,\n };\n\n const newPosition = calculateBestPosition(paddedRect);\n\n // Prevent infinite loops by only updating if values actually changed\n setCoords(prev => {\n if (prev && \n prev.top === newCoords.top && \n prev.left === newCoords.left && \n prev.width === newCoords.width && \n prev.height === newCoords.height) {\n return prev;\n }\n return newCoords;\n });\n\n setPosition(prev => {\n if (prev.top === newPosition.top && prev.left === newPosition.left) {\n return prev;\n }\n return newPosition;\n });\n } else {\n setCoords(null);\n }\n }, [currentStep, calculateBestPosition, config.style]);\n\n useEffect(() => {\n updateCoords();\n window.addEventListener('resize', updateCoords);\n window.addEventListener('scroll', updateCoords);\n\n const observer = new MutationObserver(updateCoords);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true });\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(updateCoords);\n resizeObserver.observe(document.body);\n \n const element = currentStep?.attribute \n ? document.querySelector(`[data-onboarding-id=\"${currentStep.attribute}\"]`) \n : null;\n if (element) {\n resizeObserver.observe(element);\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateCoords);\n window.removeEventListener('scroll', updateCoords);\n observer.disconnect();\n if (resizeObserver) resizeObserver.disconnect();\n };\n }, [updateCoords, currentStep?.attribute]);\n\n if (!currentStep || !coords) return null;\n\n const maskStyle = {\n ...config.style?.background,\n transition: 'all 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)',\n };\n\n const stopPropagation = (e: React.PointerEvent | React.MouseEvent) => {\n e.stopPropagation();\n };\n\n const ChevronLeftIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n\n const ChevronRightIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n\n const XIcon = () => (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n );\n\n const overlayContent = (\n <div className=\"fixed inset-0 z-[999999] pointer-events-none\">\n {/* Top Mask */}\n <div\n style={{ height: coords.top, ...maskStyle }}\n className=\"onboard-overlay-mask top-0 left-0 w-full pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Bottom Mask */}\n <div\n style={{ top: coords.top + coords.height, height: `calc(100vh - ${coords.top + coords.height}px)`, ...maskStyle }}\n className=\"onboard-overlay-mask left-0 w-full pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Left Mask */}\n <div\n style={{ top: coords.top, height: coords.height, width: coords.left, ...maskStyle }}\n className=\"onboard-overlay-mask left-0 pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n {/* Right Mask */}\n <div\n style={{ \n top: coords.top, \n height: coords.height, \n left: coords.left + coords.width, \n width: `calc(100% - ${coords.left + coords.width}px)`, \n ...maskStyle \n }}\n className=\"onboard-overlay-mask pointer-events-auto\"\n onPointerDown={stopPropagation}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n />\n\n {/* Tooltip */}\n <div\n ref={tooltipRef}\n className=\"onboard-tooltip pointer-events-auto\"\n onPointerDown={handlePointerDown}\n style={{ \n zIndex: 1000000, \n ...config.style?.container,\n top: position.top + dragOffset.y,\n left: position.left + dragOffset.x,\n transition: 'top 0.3s cubic-bezier(0.25, 0.1, 0.25, 1), left 0.3s cubic-bezier(0.25, 0.1, 0.25, 1)',\n cursor: config.metadata.draggable ? 'grab' : 'auto',\n touchAction: 'none' // Prevent scrolling on touch devices while dragging\n }}\n onMouseDown={stopPropagation}\n onClick={stopPropagation}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '8px' }}>\n <h3 style={{ margin: 0, fontWeight: 'bold', color: '#111827', fontSize: '18px', lineHeight: 1.2 }}>{currentStep.title}</h3>\n <button \n onClick={(e) => { e.stopPropagation(); finish(); }}\n style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '4px', color: '#9ca3af' }}\n >\n <XIcon />\n </button>\n </div>\n <p style={{ margin: 0, color: '#4b5563', fontSize: '14px', marginBottom: '24px', lineHeight: 1.5 }}>\n {currentStep.description}\n </p>\n \n <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>\n <button\n onClick={(e) => { e.stopPropagation(); prevStep(); }}\n disabled={isFirstStep}\n className=\"onboard-button-ghost\"\n style={{ \n background: 'none', \n border: 'none', \n cursor: isFirstStep ? 'not-allowed' : 'pointer',\n ...config.style?.prev \n }}\n >\n <ChevronLeftIcon />\n Prev\n </button>\n \n {isLastStep ? (\n <button\n onClick={(e) => { e.stopPropagation(); finish(); }}\n className=\"onboard-button-primary\"\n style={{ border: 'none', cursor: 'pointer', ...config.style?.finish }}\n >\n Finish\n </button>\n ) : (\n <button\n onClick={(e) => { e.stopPropagation(); nextStep(); }}\n className=\"onboard-button-primary\"\n style={{ \n border: 'none', \n cursor: 'pointer',\n ...(isFirstStep ? config.style?.start : {}),\n ...(!isFirstStep ? config.style?.next : {})\n }}\n >\n {isFirstStep && config.style?.start ? 'Start' : 'Next'}\n {!(isFirstStep && config.style?.start) && <ChevronRightIcon />}\n </button>\n )}\n </div>\n </div>\n </div>\n );\n\n return typeof document !== 'undefined' \n ? createPortal(overlayContent, document.body) \n : null;\n};\n"],"mappings":"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","names":["React","createContext","useContext","useEffect","useState","useCallback","useMemo","Cookies","useState","useEffect","useCallback","useRef","createPortal","jsx","jsxs","OnboardingOverlay","config","currentStep","nextStep","prevStep","finish","isFirstStep","isLastStep","useOnboarding","coords","setCoords","useState","position","setPosition","dragOffset","setDragOffset","isDragging","useRef","dragStart","tooltipRef","useEffect","handlePointerDown","e","handlePointerMove","handlePointerUp","useCallback","newX","newY","calculateBestPosition","rect","spaceAbove","spaceBelow","spaceLeft","spaceRight","top","left","updateCoords","element","padding","paddedRect","newCoords","newPosition","prev","observer","resizeObserver","maskStyle","stopPropagation","ChevronLeftIcon","ChevronRightIcon","XIcon","overlayContent","createPortal","Fragment","jsx","jsxs","OnboardingContext","createContext","COOKIE_NAME","OnboardingProvider","config","ssr","children","isMounted","setIsMounted","useState","state","setState","configRef","React","useEffect","handleNavigation","useCallback","link","isMatch","step","path","pattern","currentConfig","currentPath","matchedStepIndex","savedState","Cookies","parsed","prev","e","currentStep","useMemo","isFirstStep","isLastStep","totalSteps","isLastMainStep","hasSubSteps","nextStep","currentActiveStep","element","nextSubIndex","nextSubStep","nextIndex","nextStepObj","prevStep","prevIndex","prevStepObj","prevSubStepIndex","finish","goToStep","stepIndex","subStepIndex","value","OnboardingOverlay","useOnboarding","context","useContext"]}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "onboard-engine",
3
+ "version": "1.0.0",
4
+ "main": "./dist/index.js",
5
+ "module": "./dist/index.mjs",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js"
12
+ },
13
+ "./index.css": "./dist/index.css",
14
+ "./dist/index.css": "./dist/index.css"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "dev": "tsup --watch",
21
+ "build": "tsup",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "lint": "tsc --noEmit",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "private": false,
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/Forsrobin/onboard-engine.git"
31
+ },
32
+ "keywords": [],
33
+ "author": "",
34
+ "license": "ISC",
35
+ "type": "commonjs",
36
+ "bugs": {
37
+ "url": "https://github.com/Forsrobin/onboard-engine/issues"
38
+ },
39
+ "homepage": "https://github.com/Forsrobin/onboard-engine#readme",
40
+ "peerDependencies": {
41
+ "react": ">=18",
42
+ "react-dom": ">=18"
43
+ },
44
+ "devDependencies": {
45
+ "@testing-library/jest-dom": "^6.6.3",
46
+ "@testing-library/react": "^16.2.0",
47
+ "@types/js-cookie": "^3.0.6",
48
+ "@types/node": "^22.10.6",
49
+ "@types/react": "^19.0.7",
50
+ "@types/react-dom": "^19.0.3",
51
+ "@vitejs/plugin-react": "^4.3.4",
52
+ "jsdom": "^26.0.0",
53
+ "tsup": "^8.3.5",
54
+ "typescript": "^5.7.3",
55
+ "vitest": "^2.1.8"
56
+ },
57
+ "dependencies": {
58
+ "clsx": "^2.1.1",
59
+ "js-cookie": "^3.0.5",
60
+ "tailwind-merge": "^2.6.0"
61
+ }
62
+ }