webdrive 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,6 +43,26 @@ bun add webdrive
43
43
 
44
44
  ---
45
45
 
46
+ ## 🤖 AI Agent Skill Installation
47
+
48
+ `webdrive` includes an official **Agent Skill** so AI coding assistants (Google Antigravity, Claude Code, Cursor, GitHub Copilot) can automatically help you scaffold, configure, and troubleshoot tours.
49
+
50
+ ### Option A: Using WebDrive CLI (Instant)
51
+
52
+ ```bash
53
+ npx webdrive install-skill
54
+ ```
55
+
56
+ This installs `SKILL.md` into your project's `.agents/skills/webdrive/` folder.
57
+
58
+ ### Option B: Using the Agent Skills Ecosystem
59
+
60
+ ```bash
61
+ npx skills add Abhi-6284/webdrive
62
+ ```
63
+
64
+ ---
65
+
46
66
  ## 🚀 Quick Start
47
67
 
48
68
  ### 1. Import CSS & JavaScript
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ const pkg = JSON.parse(
11
+ fs.readFileSync(path.resolve(__dirname, "../package.json"), "utf8")
12
+ );
13
+
14
+ const args = process.argv.slice(2);
15
+ const command = args[0];
16
+
17
+ function printHelp() {
18
+ console.log(`
19
+ \x1b[1m\x1b[34mWebDrive CLI\x1b[0m v${pkg.version}
20
+ Framework-Agnostic UI Tour & Onboarding Library
21
+
22
+ \x1b[1mUsage:\x1b[0m
23
+ webdrive <command> [options]
24
+ npx webdrive <command> [options]
25
+
26
+ \x1b[1mCommands:\x1b[0m
27
+ install-skill Install the WebDrive AI Agent Skill into your project
28
+ help, --help Display this help message
29
+ --version, -v Display the current version
30
+
31
+ \x1b[1mOptions for install-skill:\x1b[0m
32
+ --target <dir> Custom destination directory (default: .agents/skills/webdrive)
33
+ --all Also install to .claude/skills and skills/
34
+
35
+ \x1b[1mExamples:\x1b[0m
36
+ npx webdrive install-skill
37
+ npx skills add Abhi-6284/webdrive
38
+ `);
39
+ }
40
+
41
+ function installSkill() {
42
+ const cwd = process.cwd();
43
+ const sourceSkillPath = path.resolve(__dirname, "../skills/webdrive/SKILL.md");
44
+
45
+ if (!fs.existsSync(sourceSkillPath)) {
46
+ console.error(`\x1b[31mError: Source SKILL.md not found at ${sourceSkillPath}\x1b[0m`);
47
+ process.exit(1);
48
+ }
49
+
50
+ const skillContent = fs.readFileSync(sourceSkillPath, "utf8");
51
+
52
+ // Determine target directories
53
+ let targets = [path.join(cwd, ".agents", "skills", "webdrive")];
54
+
55
+ const targetFlagIdx = args.indexOf("--target");
56
+ if (targetFlagIdx !== -1 && args[targetFlagIdx + 1]) {
57
+ targets = [path.resolve(cwd, args[targetFlagIdx + 1])];
58
+ } else if (args.includes("--all")) {
59
+ targets = [
60
+ path.join(cwd, ".agents", "skills", "webdrive"),
61
+ path.join(cwd, ".claude", "skills", "webdrive"),
62
+ path.join(cwd, "skills", "webdrive"),
63
+ ];
64
+ }
65
+
66
+ console.log(`\x1b[36mInstalling WebDrive AI Agent Skill...\x1b[0m`);
67
+
68
+ for (const targetDir of targets) {
69
+ fs.mkdirSync(targetDir, { recursive: true });
70
+ const destPath = path.join(targetDir, "SKILL.md");
71
+ fs.writeFileSync(destPath, skillContent, "utf8");
72
+ const relativePath = path.relative(cwd, destPath);
73
+ console.log(`\x1b[32m✔ Installed skill to:\x1b[0m ${relativePath}`);
74
+ }
75
+
76
+ console.log(`
77
+ \x1b[32m✔ Success!\x1b[0m WebDrive Agent Skill is now ready.
78
+ AI agents (Antigravity, Claude Code, Cursor, Copilot) can now assist you in building,
79
+ customizing, and debugging WebDrive tours automatically.
80
+ `);
81
+ }
82
+
83
+ switch (command) {
84
+ case "install-skill":
85
+ case "skill":
86
+ case "skill:install":
87
+ case "add-skill":
88
+ installSkill();
89
+ break;
90
+
91
+ case "-v":
92
+ case "--version":
93
+ case "version":
94
+ console.log(`webdrive v${pkg.version}`);
95
+ break;
96
+
97
+ case "help":
98
+ case "--help":
99
+ case "-h":
100
+ printHelp();
101
+ break;
102
+
103
+ default:
104
+ if (!command) {
105
+ printHelp();
106
+ } else {
107
+ console.log(`Unknown command: ${command}`);
108
+ printHelp();
109
+ process.exit(1);
110
+ }
111
+ break;
112
+ }
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "webdrive",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "Production-ready, accessible, framework-agnostic TypeScript UI tour and onboarding walkthrough library",
6
6
  "author": "webdrive",
7
7
  "license": "MIT",
8
+ "bin": {
9
+ "webdrive": "./bin/webdrive.js"
10
+ },
8
11
  "keywords": [
9
12
  "tour",
10
13
  "onboarding",
@@ -30,6 +33,8 @@
30
33
  },
31
34
  "files": [
32
35
  "dist",
36
+ "bin",
37
+ "skills",
33
38
  "README.md",
34
39
  "LICENSE"
35
40
  ],
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: webdrive
3
+ description: >-
4
+ Guide for implementing, configuring, and troubleshooting UI product tours, feature walkthroughs,
5
+ and onboarding flows using webdrive (framework-agnostic TypeScript library).
6
+ Use this skill whenever adding an onboarding tour, step-by-step guide, feature highlight, or popover
7
+ walkthrough in Vanilla JS, React, Next.js, Vue, Nuxt, Angular, Svelte, or any web app.
8
+ ---
9
+
10
+ # WebDrive — UI Tour & Onboarding Skill
11
+
12
+ `webdrive` is a production-ready, framework-agnostic TypeScript UI tour and onboarding library with zero runtime dependencies. It uses a non-destructive SVG cutout mask to highlight target elements without altering stacking contexts, z-index, or CSS transforms.
13
+
14
+ ## Quick Installation & Setup
15
+
16
+ ```bash
17
+ npm install webdrive
18
+ ```
19
+
20
+ ### Essential Imports
21
+
22
+ ```typescript
23
+ import { WebDrive } from "webdrive";
24
+ import "webdrive/styles.css";
25
+ ```
26
+
27
+ > **IMPORTANT:** In Next.js App Router, always import and initialize `WebDrive` inside Client Components (`"use client"`). It is 100% SSR-safe and will never crash on server evaluation.
28
+
29
+ ---
30
+
31
+ ## Standard Tour Pattern
32
+
33
+ ```typescript
34
+ const tour = new WebDrive({
35
+ id: "onboarding-tour", // Used for persistence
36
+ steps: [
37
+ {
38
+ element: "#navigation",
39
+ title: "Navigation",
40
+ description: "Quickly jump to any section of the app.",
41
+ position: "right", // "top" | "right" | "bottom" | "left"
42
+ align: "start", // "start" | "center" | "end"
43
+ },
44
+ {
45
+ element: "#metrics-card",
46
+ title: "Key Metrics",
47
+ description: "Track real-time analytics and revenue performance.",
48
+ position: "bottom",
49
+ align: "center",
50
+ },
51
+ {
52
+ element: "#profile-button",
53
+ title: "Account Settings",
54
+ description: "Manage your profile, team members, and preferences.",
55
+ position: "left",
56
+ align: "end",
57
+ },
58
+ ],
59
+ showProgress: true,
60
+ animate: true,
61
+ smoothScroll: true,
62
+ keyboardNavigation: true,
63
+ allowClose: true,
64
+ remember: true, // Persists completion in localStorage
65
+ });
66
+
67
+ // Start the tour
68
+ tour.start();
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Step Options Reference
74
+
75
+ | Property | Type | Description |
76
+ | :--- | :--- | :--- |
77
+ | `element` | `string \| HTMLElement` | Target CSS selector or DOM element (Required) |
78
+ | `title` | `string` | Header title |
79
+ | `description` | `string` | Safe text content for the popover card |
80
+ | `content` | `string` | Custom HTML content when rich markup is needed |
81
+ | `position` | `"top" \| "right" \| "bottom" \| "left"` | Preferred popover placement (default: `"bottom"`) |
82
+ | `align` | `"start" \| "center" \| "end"` | Alignment along target axis (default: `"center"`) |
83
+ | `padding` | `number` | Padding around cutout in pixels (default: `8`) |
84
+ | `offset` | `number` | Distance between target and popover in px (default: `12`) |
85
+ | `showNextButton` | `boolean` | Whether to display the Next button |
86
+ | `showPreviousButton`| `boolean` | Whether to display the Previous button |
87
+ | `showCloseButton` | `boolean` | Whether to display the Close button |
88
+ | `nextButtonText` | `string` | Custom label for Next button |
89
+ | `previousButtonText`| `string` | Custom label for Previous button |
90
+ | `doneButtonText` | `string` | Custom label for Done button on final step |
91
+ | `closeButtonText` | `string` | Custom label / aria-label for Close button |
92
+ | `onEnter` | `() => void \| Promise<void>` | Callback when entering step |
93
+ | `onLeave` | `() => void \| Promise<void>` | Callback when leaving step |
94
+
95
+ ---
96
+
97
+ ## Dynamic Elements & Async Content
98
+
99
+ If a target element is created dynamically or loads after an API call:
100
+
101
+ ```typescript
102
+ const tour = new WebDrive({
103
+ missingElementBehavior: "wait", // "wait" | "skip" | "stop"
104
+ missingElementWaitTimeout: 4000, // Timeout in ms before falling back
105
+ steps: [
106
+ { element: "#async-chart", title: "Charts", description: "Loaded dynamically." }
107
+ ]
108
+ });
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Framework Recipes
114
+
115
+ ### React & Next.js (`"use client"`)
116
+
117
+ ```tsx
118
+ "use client";
119
+
120
+ import { useEffect, useRef } from "react";
121
+ import { WebDrive } from "webdrive";
122
+ import "webdrive/styles.css";
123
+
124
+ export function ProductTour() {
125
+ const tourRef = useRef<WebDrive | null>(null);
126
+
127
+ useEffect(() => {
128
+ tourRef.current = new WebDrive({
129
+ id: "app-intro",
130
+ remember: true,
131
+ steps: [
132
+ { element: "#sidebar", title: "Menu", description: "Navigate here." },
133
+ { element: "#main-cta", title: "Action", description: "Get started here." }
134
+ ]
135
+ });
136
+
137
+ tourRef.current.start();
138
+
139
+ return () => {
140
+ tourRef.current?.destroy();
141
+ };
142
+ }, []);
143
+
144
+ return null;
145
+ }
146
+ ```
147
+
148
+ ### Vue 3 / Nuxt
149
+
150
+ ```vue
151
+ <script setup>
152
+ import { onMounted, onUnmounted } from "vue";
153
+ import { WebDrive } from "webdrive";
154
+ import "webdrive/styles.css";
155
+
156
+ let tour = null;
157
+
158
+ onMounted(() => {
159
+ tour = new WebDrive({
160
+ steps: [
161
+ { element: "#header", title: "Header", description: "Overview." }
162
+ ]
163
+ });
164
+ tour.start();
165
+ });
166
+
167
+ onUnmounted(() => {
168
+ tour?.destroy();
169
+ });
170
+ </script>
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Theming & Styling
176
+
177
+ Customize colors using CSS custom properties:
178
+
179
+ ```css
180
+ :root {
181
+ --webdrive-background: #ffffff;
182
+ --webdrive-foreground: #0f172a;
183
+ --webdrive-border: #e2e8f0;
184
+ --webdrive-primary: #2563eb;
185
+ --webdrive-primary-foreground: #ffffff;
186
+ --webdrive-muted: #64748b;
187
+ --webdrive-overlay: rgba(0, 0, 0, 0.6);
188
+ --webdrive-radius: 0.75rem;
189
+ --webdrive-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
190
+ --webdrive-z-index: 100000;
191
+ }
192
+
193
+ /* Dark Mode automatically applied when .dark or [data-theme="dark"] is present */
194
+ .dark {
195
+ --webdrive-background: #0f172a;
196
+ --webdrive-foreground: #f8fafc;
197
+ --webdrive-border: #1e293b;
198
+ --webdrive-primary: #3b82f6;
199
+ }
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Best Practices & Troubleshooting
205
+
206
+ 1. **Always cleanup on unmount:** Call `tour.destroy()` in React's cleanup function, Vue's `onUnmounted`, or Svelte's `onDestroy` to remove DOM elements and listeners.
207
+ 2. **Never hardcode generic IDs:** Prefer unique IDs or data attributes (e.g. `[data-tour="search-input"]`).
208
+ 3. **Reset tour completion during testing:**
209
+ ```typescript
210
+ await tour.reset(); // Clears completion status for this tour
211
+ ```
212
+ 4. **Do not modify application DOM styles:** WebDrive handles overlays and highlights externally without mutating the target element's styling.