torchlit 0.1.0 → 0.2.1
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 +60 -249
- package/dist/deep-query-vkmcq1Dw.js +16 -0
- package/dist/deep-query-vkmcq1Dw.js.map +1 -0
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/tour-overlay.d.ts +40 -2
- package/dist/tour-overlay.d.ts.map +1 -1
- package/dist/tour-overlay.js +450 -60
- package/dist/tour-overlay.js.map +1 -1
- package/dist/tour-service.d.ts +2 -2
- package/dist/tour-service.d.ts.map +1 -1
- package/dist/tour-service.js +192 -3
- package/dist/tour-service.js.map +1 -1
- package/dist/types.d.ts +38 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +15 -12
- package/dist/tour-service-BKz7eeWb.js +0 -204
- package/dist/tour-service-BKz7eeWb.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<br />
|
|
3
|
-
<img src="
|
|
3
|
+
<img src="assets/logo.svg" width="80" height="80" alt="Torchlit logo" />
|
|
4
4
|
<br />
|
|
5
5
|
</p>
|
|
6
6
|
|
|
@@ -12,10 +12,15 @@
|
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
15
|
-
<a href="https://
|
|
15
|
+
<a href="https://github.com/barryking/torchlit/actions/workflows/ci.yml"><img src="https://github.com/barryking/torchlit/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
|
|
16
|
+
<a href="https://www.npmjs.com/package/torchlit"><img src="https://img.shields.io/npm/v/torchlit?color=F26122&label=npm" alt="npm version" /></a>
|
|
16
17
|
<img src="https://img.shields.io/bundlephobia/minzip/torchlit?label=gzip" alt="bundle size" />
|
|
17
|
-
<img src="https://img.shields.io/badge/lit-%5E3.0-
|
|
18
|
-
<img src="https://img.shields.io/badge/license-MIT-
|
|
18
|
+
<img src="https://img.shields.io/badge/lit-%5E3.0-2F80ED" alt="lit peer" />
|
|
19
|
+
<img src="https://img.shields.io/badge/license-MIT-27AE60" alt="license" />
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<a href="https://barryking.github.io/torchlit/"><strong>Docs & Live Demo</strong></a>
|
|
19
24
|
</p>
|
|
20
25
|
|
|
21
26
|
---
|
|
@@ -28,9 +33,11 @@ Most tour libraries break the moment your UI uses Shadow DOM. Torchlit was built
|
|
|
28
33
|
|---|:---:|:---:|:---:|:---:|
|
|
29
34
|
| Shadow DOM traversal | **Yes** | No | No | No |
|
|
30
35
|
| Framework agnostic | **Yes** | Yes | Yes | React only |
|
|
31
|
-
| Bundle size (gzip) | **~
|
|
36
|
+
| Bundle size (gzip) | **~9 KB** | ~50 KB | ~15 KB | ~40 KB |
|
|
32
37
|
| Web Component | **Yes** | No | No | No |
|
|
38
|
+
| Accessibility (ARIA + focus trap) | **Yes** | Partial | Partial | Yes |
|
|
33
39
|
| CSS custom property theming | **Yes** | No | Partial | No |
|
|
40
|
+
| Smart auto-positioning | **Yes** | Yes | No | Yes |
|
|
34
41
|
| Async `beforeShow` hooks | **Yes** | Yes | No | Yes |
|
|
35
42
|
| Zero runtime dependencies | **Yes** | Popper.js | No | React |
|
|
36
43
|
|
|
@@ -53,10 +60,8 @@ npm install torchlit lit
|
|
|
53
60
|
import { createTourService } from 'torchlit';
|
|
54
61
|
import 'torchlit/overlay'; // registers <torchlit-overlay>
|
|
55
62
|
|
|
56
|
-
// 1. Create a service
|
|
57
63
|
const tours = createTourService();
|
|
58
64
|
|
|
59
|
-
// 2. Register a tour
|
|
60
65
|
tours.register({
|
|
61
66
|
id: 'welcome',
|
|
62
67
|
name: 'Welcome',
|
|
@@ -74,26 +79,14 @@ tours.register({
|
|
|
74
79
|
message: 'Use the sidebar to move between pages.',
|
|
75
80
|
placement: 'right',
|
|
76
81
|
},
|
|
77
|
-
{
|
|
78
|
-
target: 'search-bar',
|
|
79
|
-
title: 'Search',
|
|
80
|
-
message: 'Find anything instantly.',
|
|
81
|
-
placement: 'bottom',
|
|
82
|
-
beforeShow: async () => {
|
|
83
|
-
// Navigate, load data, or do any async prep work
|
|
84
|
-
await router.push('/search');
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
82
|
],
|
|
88
83
|
onComplete: () => analytics.track('tour_finished'),
|
|
89
84
|
onSkip: () => analytics.track('tour_skipped'),
|
|
90
85
|
});
|
|
91
86
|
|
|
92
|
-
// 3. Wire the overlay
|
|
93
87
|
const overlay = document.querySelector('torchlit-overlay');
|
|
94
88
|
overlay.service = tours;
|
|
95
89
|
|
|
96
|
-
// 4. Auto-start on first visit
|
|
97
90
|
if (tours.shouldAutoStart('welcome')) {
|
|
98
91
|
setTimeout(() => tours.start('welcome'), 800);
|
|
99
92
|
}
|
|
@@ -110,8 +103,6 @@ That's it. The spotlight finds elements even inside shadow roots.
|
|
|
110
103
|
|
|
111
104
|
## Tree-Shakeable Imports
|
|
112
105
|
|
|
113
|
-
Import only what you need:
|
|
114
|
-
|
|
115
106
|
```typescript
|
|
116
107
|
// Full library (service + overlay + types + deepQuery)
|
|
117
108
|
import { createTourService, TorchlitOverlay, deepQuery } from 'torchlit';
|
|
@@ -125,227 +116,22 @@ import { TorchlitOverlay } from 'torchlit/overlay';
|
|
|
125
116
|
|
|
126
117
|
The `torchlit/service` entry point has **zero dependencies** and can be used with any rendering layer.
|
|
127
118
|
|
|
128
|
-
##
|
|
129
|
-
|
|
130
|
-
### `createTourService(config?)`
|
|
131
|
-
|
|
132
|
-
Creates a new `TourService` instance.
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
const tours = createTourService({
|
|
136
|
-
storageKey: 'my-app-tours', // localStorage key (default: 'torchlit-state')
|
|
137
|
-
storage: sessionStorage, // any { getItem, setItem } adapter
|
|
138
|
-
targetAttribute: 'data-tour-id', // attribute for target lookup (default)
|
|
139
|
-
spotlightPadding: 10, // px around spotlight cutout (default: 10)
|
|
140
|
-
});
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
#### `TourConfig`
|
|
144
|
-
|
|
145
|
-
| Property | Type | Default | Description |
|
|
146
|
-
|---|---|---|---|
|
|
147
|
-
| `storageKey` | `string` | `'torchlit-state'` | Key for persisting completed/dismissed state |
|
|
148
|
-
| `storage` | `StorageAdapter` | `localStorage` | Any object with `getItem` / `setItem` |
|
|
149
|
-
| `targetAttribute` | `string` | `'data-tour-id'` | The data attribute used to locate targets |
|
|
150
|
-
| `spotlightPadding` | `number` | `10` | Padding in pixels around the spotlight |
|
|
151
|
-
|
|
152
|
-
### `TourService`
|
|
153
|
-
|
|
154
|
-
| Method | Description |
|
|
155
|
-
|---|---|
|
|
156
|
-
| `register(tour)` | Register a single `TourDefinition` |
|
|
157
|
-
| `register(tours[])` | Register multiple tours at once |
|
|
158
|
-
| `start(tourId)` | Start a tour by ID |
|
|
159
|
-
| `nextStep()` | Advance to the next step |
|
|
160
|
-
| `prevStep()` | Go back to the previous step |
|
|
161
|
-
| `skipTour()` | Dismiss the current tour |
|
|
162
|
-
| `isActive()` | Whether a tour is currently running |
|
|
163
|
-
| `shouldAutoStart(tourId)` | Whether a first-visit tour should start |
|
|
164
|
-
| `getTour(tourId)` | Retrieve a registered tour |
|
|
165
|
-
| `getAvailableTours()` | Get all registered tours |
|
|
166
|
-
| `getSnapshot()` | Get the current step snapshot (or `null`) |
|
|
167
|
-
| `findTarget(targetId)` | Find a DOM element by tour target ID |
|
|
168
|
-
| `subscribe(listener)` | Subscribe to state changes; returns unsubscribe fn |
|
|
169
|
-
| `resetAll()` | Clear all state (useful for testing and demos) |
|
|
170
|
-
|
|
171
|
-
### `TourDefinition`
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
interface TourDefinition {
|
|
175
|
-
id: string;
|
|
176
|
-
name: string;
|
|
177
|
-
trigger: 'first-visit' | 'manual';
|
|
178
|
-
steps: TourStep[];
|
|
179
|
-
onComplete?: () => void;
|
|
180
|
-
onSkip?: () => void;
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### `TourStep`
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
interface TourStep {
|
|
188
|
-
target: string; // data-tour-id value, or '_none_' for centered card
|
|
189
|
-
title: string;
|
|
190
|
-
message: string;
|
|
191
|
-
placement: 'top' | 'bottom' | 'left' | 'right';
|
|
192
|
-
route?: string; // emits 'tour-route-change' event
|
|
193
|
-
beforeShow?: () => void | Promise<void>;
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
### `<torchlit-overlay>`
|
|
198
|
-
|
|
199
|
-
| Property | Type | Description |
|
|
200
|
-
|---|---|---|
|
|
201
|
-
| `service` | `TourService` | The service instance to subscribe to (required) |
|
|
202
|
-
|
|
203
|
-
| Event | Detail | Description |
|
|
204
|
-
|---|---|---|
|
|
205
|
-
| `tour-route-change` | `{ route: string }` | Fired when a step has a `route` property |
|
|
206
|
-
|
|
207
|
-
| CSS Part | Description |
|
|
208
|
-
|---|---|
|
|
209
|
-
| `backdrop` | The semi-transparent overlay |
|
|
210
|
-
| `spotlight` | The cutout highlight |
|
|
211
|
-
| `tooltip` | The floating tooltip card |
|
|
212
|
-
| `center-card` | The centered card (no-target steps) |
|
|
213
|
-
|
|
214
|
-
### `deepQuery(selector, root?)`
|
|
215
|
-
|
|
216
|
-
Recursively searches the DOM including shadow roots. This is the utility that powers Torchlit's Shadow DOM support, exported for standalone use.
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
import { deepQuery } from 'torchlit';
|
|
220
|
-
|
|
221
|
-
const el = deepQuery('[data-tour-id="my-element"]');
|
|
222
|
-
// Finds the element even if it's buried inside nested shadow DOMs
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
## Theming
|
|
226
|
-
|
|
227
|
-
Torchlit adapts to your app's theme via CSS custom properties. Set them on `:root` or any ancestor:
|
|
228
|
-
|
|
229
|
-
```css
|
|
230
|
-
:root {
|
|
231
|
-
--primary: #6366f1;
|
|
232
|
-
--primary-foreground: #ffffff;
|
|
233
|
-
--card: #ffffff;
|
|
234
|
-
--border: #e5e5e5;
|
|
235
|
-
--foreground: #1a1a1a;
|
|
236
|
-
--muted-foreground: #737373;
|
|
237
|
-
--muted: #f5f5f5;
|
|
238
|
-
--background: #ffffff;
|
|
239
|
-
--radius-lg: 0.75rem;
|
|
240
|
-
--radius-md: 0.5rem;
|
|
241
|
-
--radius-xl: 1rem;
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
For isolated theming (without affecting your app), use the `--tour-*` prefix:
|
|
246
|
-
|
|
247
|
-
```css
|
|
248
|
-
torchlit-overlay {
|
|
249
|
-
--tour-primary: #6366f1;
|
|
250
|
-
--tour-card: #1a1a2e;
|
|
251
|
-
--tour-foreground: #e5e5e5;
|
|
252
|
-
--tour-border: #333;
|
|
253
|
-
--tour-spotlight-radius: 1rem;
|
|
254
|
-
--tour-tooltip-radius: 0.75rem;
|
|
255
|
-
--tour-btn-radius: 0.5rem;
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Dark Mode
|
|
260
|
-
|
|
261
|
-
If your app already toggles CSS variables for dark mode, the tour overlay adapts automatically -- zero additional configuration.
|
|
262
|
-
|
|
263
|
-
## Keyboard Navigation
|
|
264
|
-
|
|
265
|
-
| Key | Action |
|
|
266
|
-
|---|---|
|
|
267
|
-
| `Arrow Right` / `Enter` | Next step |
|
|
268
|
-
| `Arrow Left` | Previous step |
|
|
269
|
-
| `Escape` | Skip / dismiss tour |
|
|
119
|
+
## Features
|
|
270
120
|
|
|
271
|
-
|
|
121
|
+
- **Shadow DOM traversal** — finds targets inside nested shadow roots automatically
|
|
122
|
+
- **Smart auto-positioning** — tooltip flips when it would clip the viewport; arrow tracks the target
|
|
123
|
+
- **MutationObserver for lazy targets** — waits for elements to appear in the DOM (great for SPAs)
|
|
124
|
+
- **Rich content** — step messages accept Lit `html` templates for bold, links, `<kbd>`, etc.
|
|
125
|
+
- **Auto-advance / timed steps** — kiosk & demo modes with animated progress bar
|
|
126
|
+
- **Looping tours** — set `loop: true` to restart from step 0 instead of completing
|
|
127
|
+
- **Configurable spotlight shape** — circle, pill, or sharp corners per step
|
|
128
|
+
- **Scroll tracking & restore** — repositions on scroll; restores scroll position when the tour ends
|
|
129
|
+
- **Keyboard navigation** — Arrow Right / Enter (next), Arrow Left (back), Escape (skip)
|
|
130
|
+
- **CSS custom property theming** — adapts to your app's design tokens, including dark mode
|
|
131
|
+
- **`::part()` styling** — style `backdrop`, `spotlight`, `tooltip`, and `center-card` from the outside
|
|
132
|
+
- **Accessible** — `role="dialog"`, `aria-modal`, `aria-live`, focus trap, focus restore
|
|
272
133
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
Use `beforeShow` to navigate before a step renders:
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
{
|
|
279
|
-
target: 'settings-panel',
|
|
280
|
-
title: 'Settings',
|
|
281
|
-
message: 'Configure your preferences here.',
|
|
282
|
-
placement: 'right',
|
|
283
|
-
beforeShow: async () => {
|
|
284
|
-
await router.push('/settings');
|
|
285
|
-
// Wait for the route transition to complete
|
|
286
|
-
await new Promise(r => setTimeout(r, 300));
|
|
287
|
-
},
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Or use the `route` property to emit a `tour-route-change` event that your app handles:
|
|
292
|
-
|
|
293
|
-
```typescript
|
|
294
|
-
{ target: 'dashboard-widget', title: '...', message: '...', placement: 'top', route: 'dashboard' }
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
```javascript
|
|
298
|
-
overlay.addEventListener('tour-route-change', (e) => {
|
|
299
|
-
router.push(`/${e.detail.route}`);
|
|
300
|
-
});
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
### Multiple Service Instances
|
|
304
|
-
|
|
305
|
-
Each call to `createTourService()` creates an independent instance. This is useful for micro-frontends:
|
|
306
|
-
|
|
307
|
-
```typescript
|
|
308
|
-
const appTours = createTourService({ storageKey: 'app-tours' });
|
|
309
|
-
const widgetTours = createTourService({ storageKey: 'widget-tours' });
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### Custom Storage
|
|
313
|
-
|
|
314
|
-
Persist tour state to an API instead of localStorage:
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
const tours = createTourService({
|
|
318
|
-
storage: {
|
|
319
|
-
getItem: (key) => fetchFromAPI(key),
|
|
320
|
-
setItem: (key, value) => postToAPI(key, value),
|
|
321
|
-
},
|
|
322
|
-
});
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
### Headless Mode (Custom UI)
|
|
326
|
-
|
|
327
|
-
Use the service without the built-in overlay:
|
|
328
|
-
|
|
329
|
-
```typescript
|
|
330
|
-
import { createTourService } from 'torchlit/service';
|
|
331
|
-
|
|
332
|
-
const tours = createTourService();
|
|
333
|
-
tours.register([...]);
|
|
334
|
-
|
|
335
|
-
tours.subscribe((snapshot) => {
|
|
336
|
-
if (!snapshot) {
|
|
337
|
-
// Tour ended
|
|
338
|
-
hideMyCustomUI();
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
// Render your own tooltip using snapshot.step, snapshot.targetRect, etc.
|
|
342
|
-
renderMyCustomTooltip(snapshot);
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
tours.start('onboarding');
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
## Running the Demo
|
|
134
|
+
> For the full API reference, theming guide, and advanced patterns, see the **[documentation site](https://barryking.github.io/torchlit/)**.
|
|
349
135
|
|
|
350
136
|
## Project Structure
|
|
351
137
|
|
|
@@ -360,31 +146,56 @@ torchlit/
|
|
|
360
146
|
deep-query.ts # Shadow DOM traversal utility
|
|
361
147
|
test/
|
|
362
148
|
tour-service.test.ts # Service unit tests (Vitest)
|
|
149
|
+
tour-overlay.test.ts # Overlay positioning & feature tests
|
|
363
150
|
deep-query.test.ts # Deep query unit tests
|
|
151
|
+
site/
|
|
152
|
+
index.html # Docs site source (builds to docs/)
|
|
364
153
|
examples/
|
|
365
|
-
index.html #
|
|
154
|
+
index.html # Example listing page
|
|
155
|
+
basic.html # Minimal tour setup
|
|
156
|
+
multi-page.html # Tour spanning multiple views
|
|
157
|
+
custom-theme.html # Custom brand theme & dark mode
|
|
158
|
+
kiosk.html # Auto-advance + looping kiosk tour
|
|
159
|
+
smart-positioning.html # Smart auto-positioning demo
|
|
160
|
+
rich-content.html # Rich HTML content in step messages
|
|
161
|
+
docs/ # Built output for GitHub Pages
|
|
366
162
|
```
|
|
367
163
|
|
|
368
|
-
## Running
|
|
164
|
+
## Running Locally
|
|
369
165
|
|
|
370
166
|
```bash
|
|
371
167
|
git clone https://github.com/barryking/torchlit.git
|
|
372
168
|
cd torchlit
|
|
373
|
-
|
|
374
|
-
|
|
169
|
+
pnpm install
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Docs site
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
pnpm dev
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Open `http://localhost:5173` to see the full documentation site with an onboarding tour, contextual help, API reference, and theme switching.
|
|
179
|
+
|
|
180
|
+
### Examples
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
pnpm dev:examples
|
|
375
184
|
```
|
|
376
185
|
|
|
377
|
-
Open `http://localhost:5173` to
|
|
186
|
+
Open `http://localhost:5173` to browse standalone examples -- basic tour, multi-page tour, custom theming, kiosk mode, and more. Each is a self-contained HTML file you can copy and adapt.
|
|
378
187
|
|
|
379
188
|
## Contributing
|
|
380
189
|
|
|
381
190
|
Contributions are welcome! Please open an issue first to discuss what you'd like to change.
|
|
382
191
|
|
|
383
192
|
```bash
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
193
|
+
pnpm install # install dependencies
|
|
194
|
+
pnpm test # run tests
|
|
195
|
+
pnpm run build # build the library
|
|
196
|
+
pnpm dev # start the docs site dev server
|
|
197
|
+
pnpm dev:examples # start the examples dev server
|
|
198
|
+
pnpm run build:demo # build the docs site to docs/ for GitHub Pages
|
|
388
199
|
```
|
|
389
200
|
|
|
390
201
|
## License
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function deepQuery(selector, root = document.body) {
|
|
2
|
+
const found = root.querySelector(selector);
|
|
3
|
+
if (found) return found;
|
|
4
|
+
const children = root.querySelectorAll("*");
|
|
5
|
+
for (const el of children) {
|
|
6
|
+
if (el.shadowRoot) {
|
|
7
|
+
const shadowResult = deepQuery(selector, el.shadowRoot);
|
|
8
|
+
if (shadowResult) return shadowResult;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
deepQuery as d
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=deep-query-vkmcq1Dw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deep-query-vkmcq1Dw.js","sources":["../src/utils/deep-query.ts"],"sourcesContent":["/**\n * Recursively search the DOM — including shadow roots — for an element\n * matching the given CSS selector.\n *\n * This is the key differentiator vs. libraries like Shepherd.js or Intro.js\n * which cannot pierce shadow DOM boundaries.\n *\n * @param selector A valid CSS selector string.\n * @param root The root element (or Document) to start searching from.\n * Defaults to `document.body`.\n * @returns The first matching `Element`, or `null`.\n *\n * @example\n * ```ts\n * import { deepQuery } from 'torchlit';\n *\n * const el = deepQuery('[data-tour-id=\"sidebar-nav\"]');\n * ```\n */\nexport function deepQuery(\n selector: string,\n root: Element | Document = document.body,\n): Element | null {\n // Try light DOM first (fast path)\n const found = root.querySelector(selector);\n if (found) return found;\n\n // Walk children that expose a shadowRoot\n const children = root.querySelectorAll('*');\n for (const el of children) {\n if (el.shadowRoot) {\n const shadowResult = deepQuery(selector, el.shadowRoot as unknown as Document);\n if (shadowResult) return shadowResult;\n }\n }\n\n return null;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,UACd,UACA,OAA2B,SAAS,MACpB;AAEhB,QAAM,QAAQ,KAAK,cAAc,QAAQ;AACzC,MAAI,MAAO,QAAO;AAGlB,QAAM,WAAW,KAAK,iBAAiB,GAAG;AAC1C,aAAW,MAAM,UAAU;AACzB,QAAI,GAAG,YAAY;AACjB,YAAM,eAAe,UAAU,UAAU,GAAG,UAAiC;AAC7E,UAAI,aAAc,QAAO;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO;AACT;"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TourService, createTourService } from "./tour-service.js";
|
|
2
2
|
import { TorchlitOverlay } from "./tour-overlay.js";
|
|
3
|
+
import { d } from "./deep-query-vkmcq1Dw.js";
|
|
3
4
|
export {
|
|
4
5
|
TorchlitOverlay,
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
TourService,
|
|
7
|
+
createTourService,
|
|
7
8
|
d as deepQuery
|
|
8
9
|
};
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
package/dist/tour-overlay.d.ts
CHANGED
|
@@ -32,19 +32,57 @@ export declare class TorchlitOverlay extends LitElement {
|
|
|
32
32
|
private snapshot;
|
|
33
33
|
private visible;
|
|
34
34
|
private unsubscribe?;
|
|
35
|
+
private previouslyFocused;
|
|
36
|
+
private autoAdvanceTimer;
|
|
37
|
+
private lastResolvedPlacement;
|
|
38
|
+
private scrollRafId;
|
|
39
|
+
private savedScrollY;
|
|
40
|
+
private activeTourId;
|
|
35
41
|
connectedCallback(): void;
|
|
36
42
|
disconnectedCallback(): void;
|
|
37
43
|
updated(changed: Map<string, unknown>): void;
|
|
44
|
+
/**
|
|
45
|
+
* After rendering, measure the tooltip's actual height and correct
|
|
46
|
+
* its position for 'top' placement (the only one that depends on
|
|
47
|
+
* tooltip height). This eliminates hardcoded height estimates.
|
|
48
|
+
*/
|
|
49
|
+
private adjustTooltipPosition;
|
|
38
50
|
private attachService;
|
|
51
|
+
private clearAutoAdvance;
|
|
52
|
+
private startAutoAdvance;
|
|
53
|
+
/**
|
|
54
|
+
* Wait for a target element to appear in the DOM using a MutationObserver.
|
|
55
|
+
* Resolves as soon as `deepQuery` finds the target, or after `timeout` ms.
|
|
56
|
+
*/
|
|
57
|
+
private waitForTarget;
|
|
39
58
|
private handleTourChange;
|
|
40
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Scroll an element into view and wait for the scroll to finish.
|
|
61
|
+
* For tall elements (> 60% of viewport), scrolls to the top so the user
|
|
62
|
+
* sees the start of the element plus the tooltip. For smaller elements,
|
|
63
|
+
* centers them in the viewport.
|
|
64
|
+
*/
|
|
65
|
+
private scrollAndSettle;
|
|
41
66
|
private handleResize;
|
|
67
|
+
/** Throttled scroll handler — refreshes the snapshot once per frame. */
|
|
68
|
+
private handleScroll;
|
|
42
69
|
private handleKeydown;
|
|
43
70
|
private handleBackdropClick;
|
|
71
|
+
private trapFocus;
|
|
72
|
+
/**
|
|
73
|
+
* Determine the best placement for the tooltip, flipping when the preferred
|
|
74
|
+
* placement would clip the viewport. Tries: preferred → opposite → perpendicular.
|
|
75
|
+
*/
|
|
76
|
+
private bestPlacement;
|
|
44
77
|
private getTooltipPosition;
|
|
45
78
|
private clampToViewport;
|
|
46
79
|
private getArrowClass;
|
|
47
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Compute the arrow's offset along the tooltip edge so it points at
|
|
82
|
+
* the center of the target element, clamped to stay within the tooltip.
|
|
83
|
+
*/
|
|
84
|
+
private getArrowOffset;
|
|
85
|
+
render(): import("lit").TemplateResult<1>;
|
|
48
86
|
private renderProgressDots;
|
|
49
87
|
private renderCenteredStep;
|
|
50
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tour-overlay.d.ts","sourceRoot":"","sources":["../src/tour-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"tour-overlay.d.ts","sourceRoot":"","sources":["../src/tour-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAIrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAWrD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,eAAgB,SAAQ,UAAU;IAG7C,OAAgB,MAAM,0BAkUpB;IAIF;;;OAGG;IAEH,OAAO,EAAG,WAAW,CAAC;IAEb,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,qBAAqB,CAA2B;IACxD,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,YAAY,CAAuB;IAIlC,iBAAiB;IAUjB,oBAAoB;IAUpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAoB9C;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,gBAAgB;IAUxB;;;OAGG;IACH,OAAO,CAAC,aAAa;YAsCP,gBAAgB;IAwF9B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAmCvB,OAAO,CAAC,YAAY,CAIlB;IAEF,wEAAwE;IACxE,OAAO,CAAC,YAAY,CAQlB;IAEF,OAAO,CAAC,aAAa,CAmBnB;IAEF,OAAO,CAAC,mBAAmB,CAGzB;IAIF,OAAO,CAAC,SAAS;IA6BjB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAsCrB,OAAO,CAAC,kBAAkB;IAqC1B,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,aAAa;IAUrB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA2Bb,MAAM;IA+Hf,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,kBAAkB;CA8E3B;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,kBAAkB,EAAE,eAAe,CAAC;KACrC;CACF"}
|