posthog-js 1.316.1 → 1.317.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.
Files changed (65) hide show
  1. package/dist/array.full.es5.js +1 -1
  2. package/dist/array.full.js +1 -1
  3. package/dist/array.full.no-external.js +1 -1
  4. package/dist/array.js +1 -1
  5. package/dist/array.no-external.js +1 -1
  6. package/dist/customizations.full.js +1 -1
  7. package/dist/element-inference.d.ts +21 -0
  8. package/dist/element-inference.js +2 -0
  9. package/dist/element-inference.js.map +1 -0
  10. package/dist/lazy-recorder.js +1 -1
  11. package/dist/main.js +1 -1
  12. package/dist/main.js.map +1 -1
  13. package/dist/module.d.ts +12 -0
  14. package/dist/module.full.d.ts +12 -0
  15. package/dist/module.full.js +1 -1
  16. package/dist/module.full.js.map +1 -1
  17. package/dist/module.full.no-external.d.ts +12 -0
  18. package/dist/module.full.no-external.js +1 -1
  19. package/dist/module.full.no-external.js.map +1 -1
  20. package/dist/module.js +1 -1
  21. package/dist/module.js.map +1 -1
  22. package/dist/module.no-external.d.ts +12 -0
  23. package/dist/module.no-external.js +1 -1
  24. package/dist/module.no-external.js.map +1 -1
  25. package/dist/posthog-recorder.js +1 -1
  26. package/dist/product-tours-preview.d.ts +12 -0
  27. package/dist/product-tours-preview.js +1 -1
  28. package/dist/product-tours-preview.js.map +1 -1
  29. package/dist/product-tours.js +1 -1
  30. package/dist/product-tours.js.map +1 -1
  31. package/dist/src/entrypoints/element-inference.es.d.ts +1 -0
  32. package/dist/src/entrypoints/product-tours.d.ts +2 -0
  33. package/dist/src/extensions/product-tours/element-inference.d.ts +30 -0
  34. package/dist/src/extensions/product-tours/index.d.ts +2 -0
  35. package/dist/src/extensions/product-tours/product-tours-utils.d.ts +2 -1
  36. package/dist/src/posthog-product-tours-types.d.ts +7 -0
  37. package/dist/surveys-preview.d.ts +12 -0
  38. package/lib/package.json +5 -1
  39. package/lib/src/entrypoints/element-inference.es.d.ts +1 -0
  40. package/lib/src/entrypoints/element-inference.es.js +8 -0
  41. package/lib/src/entrypoints/element-inference.es.js.map +1 -0
  42. package/lib/src/entrypoints/product-tours.d.ts +2 -0
  43. package/lib/src/entrypoints/product-tours.js +5 -0
  44. package/lib/src/entrypoints/product-tours.js.map +1 -1
  45. package/lib/src/extensions/product-tours/components/ProductTourTooltip.js +5 -2
  46. package/lib/src/extensions/product-tours/components/ProductTourTooltip.js.map +1 -1
  47. package/lib/src/extensions/product-tours/components/ProductTourTooltipInner.js +1 -1
  48. package/lib/src/extensions/product-tours/components/ProductTourTooltipInner.js.map +1 -1
  49. package/lib/src/extensions/product-tours/element-inference.d.ts +30 -0
  50. package/lib/src/extensions/product-tours/element-inference.js +296 -0
  51. package/lib/src/extensions/product-tours/element-inference.js.map +1 -0
  52. package/lib/src/extensions/product-tours/index.d.ts +2 -0
  53. package/lib/src/extensions/product-tours/index.js +4 -1
  54. package/lib/src/extensions/product-tours/index.js.map +1 -1
  55. package/lib/src/extensions/product-tours/preview.js +1 -1
  56. package/lib/src/extensions/product-tours/preview.js.map +1 -1
  57. package/lib/src/extensions/product-tours/product-tours-utils.d.ts +2 -1
  58. package/lib/src/extensions/product-tours/product-tours-utils.js +12 -0
  59. package/lib/src/extensions/product-tours/product-tours-utils.js.map +1 -1
  60. package/lib/src/extensions/product-tours/product-tours.js +15 -31
  61. package/lib/src/extensions/product-tours/product-tours.js.map +1 -1
  62. package/lib/src/posthog-product-tours-types.d.ts +7 -0
  63. package/lib/src/posthog-product-tours-types.js.map +1 -1
  64. package/lib/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +7 -3
@@ -0,0 +1 @@
1
+ export { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference';
@@ -1,2 +1,4 @@
1
1
  import { generateProductTours } from '../extensions/product-tours';
2
+ export { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference';
3
+ export type { InferredSelector, AutoData, SelectorGroup } from '../extensions/product-tours/element-inference';
2
4
  export default generateProductTours;
@@ -0,0 +1,30 @@
1
+ export declare function elementIsVisible(element: HTMLElement, cache: WeakMap<HTMLElement, boolean>): boolean;
2
+ export interface SelectorGroup {
3
+ cardinality: number;
4
+ cssSelectors: Array<{
5
+ css: string;
6
+ offset: number;
7
+ }>;
8
+ }
9
+ export interface AutoData {
10
+ notextGroups: SelectorGroup[];
11
+ textGroups: SelectorGroup[];
12
+ }
13
+ export interface InferredSelector {
14
+ autoData: string;
15
+ text: string | null;
16
+ excludeText?: boolean;
17
+ }
18
+ /**
19
+ * if inferSelector is the sauce, this is the nugget
20
+ *
21
+ * find an element in the dom using the element inference data
22
+ *
23
+ * 1. try each group of selectors, starting with most specific (lowest cardinality)
24
+ * 2. try each selector in the group - run the css query, go to offset
25
+ * 3. "vote" for the element if it was found
26
+ * 4. return early if any element gets majority votes
27
+ * 5. return element w/ most votes
28
+ */
29
+ export declare function findElement(selector: InferredSelector): HTMLElement | null;
30
+ export declare function getElementPath(el: HTMLElement | null, depth?: number): string | null;
@@ -2,4 +2,6 @@ import { PostHog } from '../../posthog-core';
2
2
  import { ProductTourManager } from './product-tours';
3
3
  export { ProductTourManager } from './product-tours';
4
4
  export { findElementBySelector, getElementMetadata, getProductTourStylesheet } from './product-tours-utils';
5
+ export { findElement, getElementPath } from './element-inference';
6
+ export type { InferredSelector, AutoData, SelectorGroup } from './element-inference';
5
7
  export declare function generateProductTours(posthog: PostHog, isEnabled: boolean): ProductTourManager | undefined;
@@ -1,4 +1,4 @@
1
- import { ProductTourAppearance, ProductTourSelectorError } from '../../posthog-product-tours-types';
1
+ import { ProductTourAppearance, ProductTourSelectorError, ProductTourStep } from '../../posthog-product-tours-types';
2
2
  export declare function getProductTourStylesheet(): HTMLStyleElement | null;
3
3
  export interface ElementFindResult {
4
4
  element: HTMLElement | null;
@@ -24,3 +24,4 @@ export declare function getSpotlightStyle(targetRect: DOMRect, padding?: number)
24
24
  export declare function addProductTourCSSVariablesToElement(element: HTMLElement, appearance?: ProductTourAppearance): void;
25
25
  export declare function renderTipTapContent(content: any): string;
26
26
  export declare function normalizeUrl(url: string): string;
27
+ export declare function getStepHtml(step: ProductTourStep): string;
@@ -1,5 +1,6 @@
1
1
  import { PropertyMatchType } from './types';
2
2
  import { SurveyActionType, SurveyEventWithFilters } from './posthog-surveys-types';
3
+ import type { InferredSelector } from './extensions/product-tours/element-inference';
3
4
  export interface JSONContent {
4
5
  type?: string;
5
6
  attrs?: Record<string, any>;
@@ -30,12 +31,18 @@ export interface ProductTourStep {
30
31
  selector?: string;
31
32
  progressionTrigger: 'button' | 'click';
32
33
  content: JSONContent | null;
34
+ /** Pre-rendered HTML content from the editor. If present, SDK should use this instead of rendering from JSONContent. */
35
+ contentHtml?: string;
33
36
  /** Inline survey question config - if present, this is a survey step */
34
37
  survey?: ProductTourSurveyQuestion;
35
38
  /** ID of the auto-created survey for this step (set by backend) */
36
39
  linkedSurveyId?: string;
37
40
  /** ID of the survey question (set by backend, used for event tracking) */
38
41
  linkedSurveyQuestionId?: string;
42
+ /** Enhanced element data for more reliable lookup at runtime */
43
+ inferenceData?: InferredSelector;
44
+ /** Maximum tooltip width in pixels (defaults to 320px) */
45
+ maxWidth?: number;
39
46
  }
40
47
  export interface ProductTourConditions {
41
48
  url?: string;
@@ -1623,6 +1623,12 @@ declare class PostHogFeatureFlags {
1623
1623
  reset(): void;
1624
1624
  }
1625
1625
 
1626
+ interface InferredSelector {
1627
+ autoData: string;
1628
+ text: string | null;
1629
+ excludeText?: boolean;
1630
+ }
1631
+
1626
1632
  interface JSONContent {
1627
1633
  type?: string;
1628
1634
  attrs?: Record<string, any>;
@@ -1653,12 +1659,18 @@ interface ProductTourStep {
1653
1659
  selector?: string;
1654
1660
  progressionTrigger: 'button' | 'click';
1655
1661
  content: JSONContent | null;
1662
+ /** Pre-rendered HTML content from the editor. If present, SDK should use this instead of rendering from JSONContent. */
1663
+ contentHtml?: string;
1656
1664
  /** Inline survey question config - if present, this is a survey step */
1657
1665
  survey?: ProductTourSurveyQuestion;
1658
1666
  /** ID of the auto-created survey for this step (set by backend) */
1659
1667
  linkedSurveyId?: string;
1660
1668
  /** ID of the survey question (set by backend, used for event tracking) */
1661
1669
  linkedSurveyQuestionId?: string;
1670
+ /** Enhanced element data for more reliable lookup at runtime */
1671
+ inferenceData?: InferredSelector;
1672
+ /** Maximum tooltip width in pixels (defaults to 320px) */
1673
+ maxWidth?: number;
1662
1674
  }
1663
1675
  interface ProductTourConditions {
1664
1676
  url?: string;
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthog-js",
3
- "version": "1.316.1",
3
+ "version": "1.317.0",
4
4
  "description": "Posthog-js allows you to automatically capture usage and send events to PostHog.",
5
5
  "repository": "https://github.com/PostHog/posthog-js",
6
6
  "author": "hey@posthog.com",
@@ -52,8 +52,10 @@
52
52
  "@posthog/core": "workspace:*",
53
53
  "@posthog/types": "workspace:*",
54
54
  "core-js": "^3.38.1",
55
+ "dompurify": "^3.3.1",
55
56
  "fflate": "^0.4.8",
56
57
  "preact": "^10.19.3",
58
+ "query-selector-shadow-dom": "^1.0.1",
57
59
  "web-vitals": "^4.2.4"
58
60
  },
59
61
  "devDependencies": {
@@ -83,9 +85,11 @@
83
85
  "@testing-library/dom": "catalog:",
84
86
  "@testing-library/jest-dom": "catalog:",
85
87
  "@testing-library/preact": "catalog:",
88
+ "@types/dompurify": "^3.2.0",
86
89
  "@types/dotenv": "^8.2.3",
87
90
  "@types/jest": "catalog:",
88
91
  "@types/node": "^22.5.0",
92
+ "@types/query-selector-shadow-dom": "^1.0.4",
89
93
  "@types/sinon": "^17.0.1",
90
94
  "@types/web": "^0.0.222",
91
95
  "babel-jest": "^29.7.0",
@@ -0,0 +1 @@
1
+ export { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.elementIsVisible = exports.getElementPath = exports.findElement = void 0;
4
+ var element_inference_1 = require("../extensions/product-tours/element-inference");
5
+ Object.defineProperty(exports, "findElement", { enumerable: true, get: function () { return element_inference_1.findElement; } });
6
+ Object.defineProperty(exports, "getElementPath", { enumerable: true, get: function () { return element_inference_1.getElementPath; } });
7
+ Object.defineProperty(exports, "elementIsVisible", { enumerable: true, get: function () { return element_inference_1.elementIsVisible; } });
8
+ //# sourceMappingURL=element-inference.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-inference.es.js","sourceRoot":"","sources":["../../../src/entrypoints/element-inference.es.ts"],"names":[],"mappings":";;;AAAA,mFAA6G;AAApG,gHAAA,WAAW,OAAA;AAAE,mHAAA,cAAc,OAAA;AAAE,qHAAA,gBAAgB,OAAA","sourcesContent":["export { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference'\n"]}
@@ -1,2 +1,4 @@
1
1
  import { generateProductTours } from '../extensions/product-tours';
2
+ export { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference';
3
+ export type { InferredSelector, AutoData, SelectorGroup } from '../extensions/product-tours/element-inference';
2
4
  export default generateProductTours;
@@ -1,8 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.elementIsVisible = exports.getElementPath = exports.findElement = void 0;
3
4
  var product_tours_1 = require("../extensions/product-tours");
4
5
  var globals_1 = require("../utils/globals");
5
6
  globals_1.assignableWindow.__PosthogExtensions__ = globals_1.assignableWindow.__PosthogExtensions__ || {};
6
7
  globals_1.assignableWindow.__PosthogExtensions__.generateProductTours = product_tours_1.generateProductTours;
8
+ var element_inference_1 = require("../extensions/product-tours/element-inference");
9
+ Object.defineProperty(exports, "findElement", { enumerable: true, get: function () { return element_inference_1.findElement; } });
10
+ Object.defineProperty(exports, "getElementPath", { enumerable: true, get: function () { return element_inference_1.getElementPath; } });
11
+ Object.defineProperty(exports, "elementIsVisible", { enumerable: true, get: function () { return element_inference_1.elementIsVisible; } });
7
12
  exports.default = product_tours_1.generateProductTours;
8
13
  //# sourceMappingURL=product-tours.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"product-tours.js","sourceRoot":"","sources":["../../../src/entrypoints/product-tours.ts"],"names":[],"mappings":";;AAAA,6DAAkE;AAClE,4CAAmD;AAEnD,0BAAgB,CAAC,qBAAqB,GAAG,0BAAgB,CAAC,qBAAqB,IAAI,EAAE,CAAA;AACrF,0BAAgB,CAAC,qBAAqB,CAAC,oBAAoB,GAAG,oCAAoB,CAAA;AAElF,kBAAe,oCAAoB,CAAA","sourcesContent":["import { generateProductTours } from '../extensions/product-tours'\nimport { assignableWindow } from '../utils/globals'\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nassignableWindow.__PosthogExtensions__.generateProductTours = generateProductTours\n\nexport default generateProductTours\n"]}
1
+ {"version":3,"file":"product-tours.js","sourceRoot":"","sources":["../../../src/entrypoints/product-tours.ts"],"names":[],"mappings":";;;AAAA,6DAAkE;AAClE,4CAAmD;AAEnD,0BAAgB,CAAC,qBAAqB,GAAG,0BAAgB,CAAC,qBAAqB,IAAI,EAAE,CAAA;AACrF,0BAAgB,CAAC,qBAAqB,CAAC,oBAAoB,GAAG,oCAAoB,CAAA;AAElF,mFAA6G;AAApG,gHAAA,WAAW,OAAA;AAAE,mHAAA,cAAc,OAAA;AAAE,qHAAA,gBAAgB,OAAA;AAGtD,kBAAe,oCAAoB,CAAA","sourcesContent":["import { generateProductTours } from '../extensions/product-tours'\nimport { assignableWindow } from '../utils/globals'\n\nassignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}\nassignableWindow.__PosthogExtensions__.generateProductTours = generateProductTours\n\nexport { findElement, getElementPath, elementIsVisible } from '../extensions/product-tours/element-inference'\nexport type { InferredSelector, AutoData, SelectorGroup } from '../extensions/product-tours/element-inference'\n\nexport default generateProductTours\n"]}
@@ -199,7 +199,10 @@ function ProductTourTooltip(_a) {
199
199
  var isSurvey = displayedStep.type === 'survey';
200
200
  // For element steps, don't render until position is calculated
201
201
  var isPositionReady = isCentered || !(0, core_1.isNull)(position);
202
- var tooltipStyle = isCentered
202
+ var tooltipStyle = __assign(__assign({}, (displayedStep.maxWidth && {
203
+ width: "".concat(displayedStep.maxWidth, "px"),
204
+ maxWidth: "".concat(displayedStep.maxWidth, "px"),
205
+ })), (isCentered
203
206
  ? {
204
207
  top: '50%',
205
208
  left: '50%',
@@ -208,7 +211,7 @@ function ProductTourTooltip(_a) {
208
211
  : {
209
212
  top: position ? "".concat(position.top, "px") : '0',
210
213
  left: position ? "".concat(position.left, "px") : '0',
211
- };
214
+ }));
212
215
  return ((0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-container", children: [(0, jsx_runtime_1.jsx)("div", { class: "ph-tour-click-overlay", onClick: handleOverlayClick }), (0, jsx_runtime_1.jsx)("div", { class: "ph-tour-modal-overlay", style: {
213
216
  opacity: isCentered && isVisible ? 1 : 0,
214
217
  transition: "opacity ".concat(TRANSITION_DURATION, "ms ease-out"),
@@ -1 +1 @@
1
- {"version":3,"file":"ProductTourTooltip.js","sourceRoot":"","sources":["../../../../../src/extensions/product-tours/components/ProductTourTooltip.tsx"],"names":[],"mappings":"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","sourcesContent":["import { h } from 'preact'\nimport { useEffect, useState, useCallback, useRef } from 'preact/hooks'\nimport { ProductTour, ProductTourStep, ProductTourDismissReason } from '../../../posthog-product-tours-types'\nimport { calculateTooltipPosition, getSpotlightStyle, TooltipPosition } from '../product-tours-utils'\nimport { addEventListener } from '../../../utils'\nimport { window as _window } from '../../../utils/globals'\nimport { ProductTourTooltipInner } from './ProductTourTooltipInner'\nimport { ProductTourSurveyStepInner } from './ProductTourSurveyStepInner'\nimport { isNull } from '@posthog/core'\n\nconst window = _window as Window & typeof globalThis\n\ntype TransitionState = 'entering' | 'visible' | 'exiting'\n\nexport interface ProductTourTooltipProps {\n tour: ProductTour\n step: ProductTourStep\n stepIndex: number\n totalSteps: number\n targetElement: HTMLElement | null\n onNext: () => void\n onPrevious: () => void\n onDismiss: (reason: ProductTourDismissReason) => void\n onSurveySubmit?: (response: string | number | null) => void\n}\n\nfunction getOppositePosition(position: TooltipPosition): TooltipPosition {\n const opposites: Record<TooltipPosition, TooltipPosition> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n }\n return opposites[position]\n}\n\nfunction scrollToElement(element: HTMLElement, resolve: () => void): void {\n const initialRect = element.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const viewportWidth = window.innerWidth\n\n const safeMarginY = viewportHeight / 6\n const safeMarginX = viewportWidth / 6\n\n const isInSafeZone =\n initialRect.top >= safeMarginY &&\n initialRect.bottom <= viewportHeight - safeMarginY &&\n initialRect.left >= safeMarginX &&\n initialRect.right <= viewportWidth - safeMarginX\n\n if (isInSafeZone) {\n resolve()\n return\n }\n\n element.scrollIntoView({ behavior: 'smooth', block: 'center' })\n\n let lastTop = initialRect.top\n let stableCount = 0\n let resolved = false\n\n const checkStability = () => {\n if (resolved) return\n\n const currentRect = element.getBoundingClientRect()\n if (Math.abs(currentRect.top - lastTop) < 1) {\n stableCount++\n if (stableCount >= 3) {\n resolved = true\n resolve()\n return\n }\n } else {\n stableCount = 0\n }\n lastTop = currentRect.top\n setTimeout(checkStability, 50)\n }\n\n setTimeout(checkStability, 30)\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true\n resolve()\n }\n }, 500)\n}\n\nconst TRANSITION_DURATION = 150\n\nexport function ProductTourTooltip({\n tour,\n step,\n stepIndex,\n totalSteps,\n targetElement,\n onNext,\n onPrevious,\n onDismiss,\n onSurveySubmit,\n}: ProductTourTooltipProps): h.JSX.Element {\n const [transitionState, setTransitionState] = useState<TransitionState>('entering')\n const [position, setPosition] = useState<ReturnType<typeof calculateTooltipPosition> | null>(null)\n const [spotlightStyle, setSpotlightStyle] = useState<ReturnType<typeof getSpotlightStyle> | null>(null)\n\n const [displayedStep, setDisplayedStep] = useState(step)\n const [displayedStepIndex, setDisplayedStepIndex] = useState(stepIndex)\n\n const previousStepRef = useRef(stepIndex)\n const isTransitioningRef = useRef(false)\n\n // Modal and survey steps are both centered on screen\n const isCentered = displayedStep.type === 'modal' || displayedStep.type === 'survey'\n\n const updatePosition = useCallback(() => {\n if (!targetElement) return\n const rect = targetElement.getBoundingClientRect()\n setPosition(calculateTooltipPosition(rect))\n setSpotlightStyle(getSpotlightStyle(rect))\n }, [targetElement])\n\n useEffect(() => {\n const currentStepIndex = stepIndex\n const isStepChange = previousStepRef.current !== stepIndex\n\n const finishEntering = () => {\n if (previousStepRef.current !== currentStepIndex) return\n setTransitionState('visible')\n isTransitioningRef.current = false\n }\n\n const enterStep = () => {\n // Only scroll/position for element steps\n if (targetElement && step.type === 'element') {\n scrollToElement(targetElement, () => {\n if (previousStepRef.current !== currentStepIndex) return\n updatePosition()\n setTimeout(finishEntering, 50)\n })\n } else {\n setTimeout(finishEntering, 50)\n }\n }\n\n if (!isStepChange) {\n previousStepRef.current = stepIndex\n isTransitioningRef.current = true\n enterStep()\n return\n }\n\n previousStepRef.current = stepIndex\n isTransitioningRef.current = true\n setTransitionState('exiting')\n\n setTimeout(() => {\n if (previousStepRef.current !== currentStepIndex) return\n\n // Reset position for element steps to prevent flash at old position\n if (step.type === 'element') {\n setPosition(null)\n setSpotlightStyle(null)\n }\n\n setDisplayedStep(step)\n setDisplayedStepIndex(stepIndex)\n setTransitionState('entering')\n\n enterStep()\n }, TRANSITION_DURATION)\n }, [targetElement, stepIndex, step, updatePosition])\n\n useEffect(() => {\n if (transitionState !== 'visible' || isCentered) return\n\n const handleUpdate = () => {\n if (!isTransitioningRef.current) {\n updatePosition()\n }\n }\n\n addEventListener(window, 'scroll', handleUpdate as EventListener, { capture: true })\n addEventListener(window, 'resize', handleUpdate as EventListener)\n\n return () => {\n window?.removeEventListener('scroll', handleUpdate, true)\n window?.removeEventListener('resize', handleUpdate)\n }\n }, [updatePosition, transitionState, isCentered])\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onDismiss('escape_key')\n }\n }\n addEventListener(window, 'keydown', handleKeyDown as EventListener)\n return () => {\n window?.removeEventListener('keydown', handleKeyDown)\n }\n }, [onDismiss])\n\n const handleOverlayClick = (e: MouseEvent) => {\n e.stopPropagation()\n onDismiss('user_clicked_outside')\n }\n\n const handleTooltipClick = (e: MouseEvent) => {\n e.stopPropagation()\n }\n\n const handleSpotlightClick = (e: MouseEvent) => {\n e.stopPropagation()\n if (targetElement) {\n targetElement.click()\n }\n onNext()\n }\n\n const isVisible = transitionState === 'visible'\n const isSurvey = displayedStep.type === 'survey'\n\n // For element steps, don't render until position is calculated\n const isPositionReady = isCentered || !isNull(position)\n\n const tooltipStyle = isCentered\n ? {\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n }\n : {\n top: position ? `${position.top}px` : '0',\n left: position ? `${position.left}px` : '0',\n }\n\n return (\n <div class=\"ph-tour-container\">\n <div class=\"ph-tour-click-overlay\" onClick={handleOverlayClick} />\n\n {/* Modal overlay - visible for centered steps */}\n <div\n class=\"ph-tour-modal-overlay\"\n style={{\n opacity: isCentered && isVisible ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n pointerEvents: isCentered ? 'auto' : 'none',\n }}\n />\n\n {/* Spotlight - visible for element steps */}\n <div\n class=\"ph-tour-spotlight\"\n style={{\n ...(isVisible && isPositionReady && spotlightStyle\n ? spotlightStyle\n : { top: '50%', left: '50%', width: '0px', height: '0px' }),\n opacity: !isCentered && isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n ...(displayedStep.progressionTrigger === 'click' &&\n !isCentered && {\n pointerEvents: 'auto',\n cursor: 'pointer',\n }),\n }}\n onClick={displayedStep.progressionTrigger === 'click' && !isCentered ? handleSpotlightClick : undefined}\n />\n\n <div\n class={`ph-tour-tooltip ${isCentered ? 'ph-tour-tooltip--modal' : ''} ${isSurvey ? 'ph-tour-survey-step' : ''}`}\n style={{\n ...tooltipStyle,\n opacity: isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n }}\n onClick={handleTooltipClick}\n >\n {!isCentered && position && (\n <div class={`ph-tour-arrow ph-tour-arrow--${getOppositePosition(position.position)}`} />\n )}\n\n {isSurvey ? (\n <ProductTourSurveyStepInner\n step={displayedStep}\n appearance={tour.appearance}\n stepIndex={displayedStepIndex}\n totalSteps={totalSteps}\n onSubmit={onSurveySubmit}\n onPrevious={onPrevious}\n onDismiss={() => onDismiss('user_clicked_skip')}\n />\n ) : (\n <ProductTourTooltipInner\n step={displayedStep}\n appearance={tour.appearance}\n stepIndex={displayedStepIndex}\n totalSteps={totalSteps}\n onNext={onNext}\n onPrevious={onPrevious}\n onDismiss={() => onDismiss('user_clicked_skip')}\n />\n )}\n </div>\n </div>\n )\n}\n"]}
1
+ {"version":3,"file":"ProductTourTooltip.js","sourceRoot":"","sources":["../../../../../src/extensions/product-tours/components/ProductTourTooltip.tsx"],"names":[],"mappings":"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","sourcesContent":["import { h } from 'preact'\nimport { useEffect, useState, useCallback, useRef } from 'preact/hooks'\nimport { ProductTour, ProductTourStep, ProductTourDismissReason } from '../../../posthog-product-tours-types'\nimport { calculateTooltipPosition, getSpotlightStyle, TooltipPosition } from '../product-tours-utils'\nimport { addEventListener } from '../../../utils'\nimport { window as _window } from '../../../utils/globals'\nimport { ProductTourTooltipInner } from './ProductTourTooltipInner'\nimport { ProductTourSurveyStepInner } from './ProductTourSurveyStepInner'\nimport { isNull } from '@posthog/core'\n\nconst window = _window as Window & typeof globalThis\n\ntype TransitionState = 'entering' | 'visible' | 'exiting'\n\nexport interface ProductTourTooltipProps {\n tour: ProductTour\n step: ProductTourStep\n stepIndex: number\n totalSteps: number\n targetElement: HTMLElement | null\n onNext: () => void\n onPrevious: () => void\n onDismiss: (reason: ProductTourDismissReason) => void\n onSurveySubmit?: (response: string | number | null) => void\n}\n\nfunction getOppositePosition(position: TooltipPosition): TooltipPosition {\n const opposites: Record<TooltipPosition, TooltipPosition> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n }\n return opposites[position]\n}\n\nfunction scrollToElement(element: HTMLElement, resolve: () => void): void {\n const initialRect = element.getBoundingClientRect()\n const viewportHeight = window.innerHeight\n const viewportWidth = window.innerWidth\n\n const safeMarginY = viewportHeight / 6\n const safeMarginX = viewportWidth / 6\n\n const isInSafeZone =\n initialRect.top >= safeMarginY &&\n initialRect.bottom <= viewportHeight - safeMarginY &&\n initialRect.left >= safeMarginX &&\n initialRect.right <= viewportWidth - safeMarginX\n\n if (isInSafeZone) {\n resolve()\n return\n }\n\n element.scrollIntoView({ behavior: 'smooth', block: 'center' })\n\n let lastTop = initialRect.top\n let stableCount = 0\n let resolved = false\n\n const checkStability = () => {\n if (resolved) return\n\n const currentRect = element.getBoundingClientRect()\n if (Math.abs(currentRect.top - lastTop) < 1) {\n stableCount++\n if (stableCount >= 3) {\n resolved = true\n resolve()\n return\n }\n } else {\n stableCount = 0\n }\n lastTop = currentRect.top\n setTimeout(checkStability, 50)\n }\n\n setTimeout(checkStability, 30)\n\n setTimeout(() => {\n if (!resolved) {\n resolved = true\n resolve()\n }\n }, 500)\n}\n\nconst TRANSITION_DURATION = 150\n\nexport function ProductTourTooltip({\n tour,\n step,\n stepIndex,\n totalSteps,\n targetElement,\n onNext,\n onPrevious,\n onDismiss,\n onSurveySubmit,\n}: ProductTourTooltipProps): h.JSX.Element {\n const [transitionState, setTransitionState] = useState<TransitionState>('entering')\n const [position, setPosition] = useState<ReturnType<typeof calculateTooltipPosition> | null>(null)\n const [spotlightStyle, setSpotlightStyle] = useState<ReturnType<typeof getSpotlightStyle> | null>(null)\n\n const [displayedStep, setDisplayedStep] = useState(step)\n const [displayedStepIndex, setDisplayedStepIndex] = useState(stepIndex)\n\n const previousStepRef = useRef(stepIndex)\n const isTransitioningRef = useRef(false)\n\n // Modal and survey steps are both centered on screen\n const isCentered = displayedStep.type === 'modal' || displayedStep.type === 'survey'\n\n const updatePosition = useCallback(() => {\n if (!targetElement) return\n const rect = targetElement.getBoundingClientRect()\n setPosition(calculateTooltipPosition(rect))\n setSpotlightStyle(getSpotlightStyle(rect))\n }, [targetElement])\n\n useEffect(() => {\n const currentStepIndex = stepIndex\n const isStepChange = previousStepRef.current !== stepIndex\n\n const finishEntering = () => {\n if (previousStepRef.current !== currentStepIndex) return\n setTransitionState('visible')\n isTransitioningRef.current = false\n }\n\n const enterStep = () => {\n // Only scroll/position for element steps\n if (targetElement && step.type === 'element') {\n scrollToElement(targetElement, () => {\n if (previousStepRef.current !== currentStepIndex) return\n updatePosition()\n setTimeout(finishEntering, 50)\n })\n } else {\n setTimeout(finishEntering, 50)\n }\n }\n\n if (!isStepChange) {\n previousStepRef.current = stepIndex\n isTransitioningRef.current = true\n enterStep()\n return\n }\n\n previousStepRef.current = stepIndex\n isTransitioningRef.current = true\n setTransitionState('exiting')\n\n setTimeout(() => {\n if (previousStepRef.current !== currentStepIndex) return\n\n // Reset position for element steps to prevent flash at old position\n if (step.type === 'element') {\n setPosition(null)\n setSpotlightStyle(null)\n }\n\n setDisplayedStep(step)\n setDisplayedStepIndex(stepIndex)\n setTransitionState('entering')\n\n enterStep()\n }, TRANSITION_DURATION)\n }, [targetElement, stepIndex, step, updatePosition])\n\n useEffect(() => {\n if (transitionState !== 'visible' || isCentered) return\n\n const handleUpdate = () => {\n if (!isTransitioningRef.current) {\n updatePosition()\n }\n }\n\n addEventListener(window, 'scroll', handleUpdate as EventListener, { capture: true })\n addEventListener(window, 'resize', handleUpdate as EventListener)\n\n return () => {\n window?.removeEventListener('scroll', handleUpdate, true)\n window?.removeEventListener('resize', handleUpdate)\n }\n }, [updatePosition, transitionState, isCentered])\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onDismiss('escape_key')\n }\n }\n addEventListener(window, 'keydown', handleKeyDown as EventListener)\n return () => {\n window?.removeEventListener('keydown', handleKeyDown)\n }\n }, [onDismiss])\n\n const handleOverlayClick = (e: MouseEvent) => {\n e.stopPropagation()\n onDismiss('user_clicked_outside')\n }\n\n const handleTooltipClick = (e: MouseEvent) => {\n e.stopPropagation()\n }\n\n const handleSpotlightClick = (e: MouseEvent) => {\n e.stopPropagation()\n if (targetElement) {\n targetElement.click()\n }\n onNext()\n }\n\n const isVisible = transitionState === 'visible'\n const isSurvey = displayedStep.type === 'survey'\n\n // For element steps, don't render until position is calculated\n const isPositionReady = isCentered || !isNull(position)\n\n const tooltipStyle = {\n ...(displayedStep.maxWidth && {\n width: `${displayedStep.maxWidth}px`,\n maxWidth: `${displayedStep.maxWidth}px`,\n }),\n ...(isCentered\n ? {\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n }\n : {\n top: position ? `${position.top}px` : '0',\n left: position ? `${position.left}px` : '0',\n }),\n }\n\n return (\n <div class=\"ph-tour-container\">\n <div class=\"ph-tour-click-overlay\" onClick={handleOverlayClick} />\n\n {/* Modal overlay - visible for centered steps */}\n <div\n class=\"ph-tour-modal-overlay\"\n style={{\n opacity: isCentered && isVisible ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n pointerEvents: isCentered ? 'auto' : 'none',\n }}\n />\n\n {/* Spotlight - visible for element steps */}\n <div\n class=\"ph-tour-spotlight\"\n style={{\n ...(isVisible && isPositionReady && spotlightStyle\n ? spotlightStyle\n : { top: '50%', left: '50%', width: '0px', height: '0px' }),\n opacity: !isCentered && isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n ...(displayedStep.progressionTrigger === 'click' &&\n !isCentered && {\n pointerEvents: 'auto',\n cursor: 'pointer',\n }),\n }}\n onClick={displayedStep.progressionTrigger === 'click' && !isCentered ? handleSpotlightClick : undefined}\n />\n\n <div\n class={`ph-tour-tooltip ${isCentered ? 'ph-tour-tooltip--modal' : ''} ${isSurvey ? 'ph-tour-survey-step' : ''}`}\n style={{\n ...tooltipStyle,\n opacity: isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n }}\n onClick={handleTooltipClick}\n >\n {!isCentered && position && (\n <div class={`ph-tour-arrow ph-tour-arrow--${getOppositePosition(position.position)}`} />\n )}\n\n {isSurvey ? (\n <ProductTourSurveyStepInner\n step={displayedStep}\n appearance={tour.appearance}\n stepIndex={displayedStepIndex}\n totalSteps={totalSteps}\n onSubmit={onSurveySubmit}\n onPrevious={onPrevious}\n onDismiss={() => onDismiss('user_clicked_skip')}\n />\n ) : (\n <ProductTourTooltipInner\n step={displayedStep}\n appearance={tour.appearance}\n stepIndex={displayedStepIndex}\n totalSteps={totalSteps}\n onNext={onNext}\n onPrevious={onPrevious}\n onDismiss={() => onDismiss('user_clicked_skip')}\n />\n )}\n </div>\n </div>\n )\n}\n"]}
@@ -13,6 +13,6 @@ function ProductTourTooltipInner(_a) {
13
13
  var showNextButton = step.progressionTrigger === 'button' || step.type === 'modal';
14
14
  var isInteractive = !!(onNext || onPrevious || onDismiss);
15
15
  var cursorStyle = isInteractive ? undefined : { cursor: 'default' };
16
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { class: "ph-tour-dismiss", onClick: onDismiss, "aria-label": "Close tour", style: cursorStyle, children: icons_1.cancelSVG }), (0, jsx_runtime_1.jsx)("div", { class: "ph-tour-content", dangerouslySetInnerHTML: { __html: (0, product_tours_utils_1.renderTipTapContent)(step.content) } }), (0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-footer", children: [(0, jsx_runtime_1.jsxs)("span", { class: "ph-tour-progress", children: [stepIndex + 1, " of ", totalSteps] }), (0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-buttons", children: [!isFirstStep && ((0, jsx_runtime_1.jsx)("button", { class: "ph-tour-button ph-tour-button--secondary", onClick: onPrevious, style: cursorStyle, children: "Back" })), showNextButton && ((0, jsx_runtime_1.jsx)("button", { class: "ph-tour-button ph-tour-button--primary", onClick: onNext, style: cursorStyle, children: isLastStep ? 'Done' : 'Next' }))] })] }), !whiteLabel && ((0, jsx_runtime_1.jsxs)("a", { href: isInteractive ? 'https://posthog.com/product-tours' : undefined, target: isInteractive ? '_blank' : undefined, rel: isInteractive ? 'noopener noreferrer' : undefined, class: "ph-tour-branding", style: isInteractive ? undefined : { cursor: 'default', pointerEvents: 'none' }, children: ["Tour by ", icons_1.IconPosthogLogo] }))] }));
16
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { class: "ph-tour-dismiss", onClick: onDismiss, "aria-label": "Close tour", style: cursorStyle, children: icons_1.cancelSVG }), (0, jsx_runtime_1.jsx)("div", { class: "ph-tour-content", dangerouslySetInnerHTML: { __html: (0, product_tours_utils_1.getStepHtml)(step) } }), (0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-footer", children: [(0, jsx_runtime_1.jsxs)("span", { class: "ph-tour-progress", children: [stepIndex + 1, " of ", totalSteps] }), (0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-buttons", children: [!isFirstStep && ((0, jsx_runtime_1.jsx)("button", { class: "ph-tour-button ph-tour-button--secondary", onClick: onPrevious, style: cursorStyle, children: "Back" })), showNextButton && ((0, jsx_runtime_1.jsx)("button", { class: "ph-tour-button ph-tour-button--primary", onClick: onNext, style: cursorStyle, children: isLastStep ? 'Done' : 'Next' }))] })] }), !whiteLabel && ((0, jsx_runtime_1.jsxs)("a", { href: isInteractive ? 'https://posthog.com/product-tours' : undefined, target: isInteractive ? '_blank' : undefined, rel: isInteractive ? 'noopener noreferrer' : undefined, class: "ph-tour-branding", style: isInteractive ? undefined : { cursor: 'default', pointerEvents: 'none' }, children: ["Tour by ", icons_1.IconPosthogLogo] }))] }));
17
17
  }
18
18
  //# sourceMappingURL=ProductTourTooltipInner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProductTourTooltipInner.js","sourceRoot":"","sources":["../../../../../src/extensions/product-tours/components/ProductTourTooltipInner.tsx"],"names":[],"mappings":";;AAeA,0DA6DC;;AA1ED,8DAA4D;AAC5D,6CAAgE;AAYhE,SAAgB,uBAAuB,CAAC,EAQT;;QAP3B,IAAI,UAAA,EACJ,UAAU,gBAAA,EACV,SAAS,eAAA,EACT,UAAU,gBAAA,EACV,MAAM,YAAA,EACN,UAAU,gBAAA,EACV,SAAS,eAAA;IAET,IAAM,UAAU,GAAG,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,mCAAI,KAAK,CAAA;IAClD,IAAM,UAAU,GAAG,SAAS,IAAI,UAAU,GAAG,CAAC,CAAA;IAC9C,IAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAA;IACnC,IAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAA;IAEpF,IAAM,aAAa,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,UAAU,IAAI,SAAS,CAAC,CAAA;IAC3D,IAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;IAErE,OAAO,CACH,6DACI,mCAAQ,KAAK,EAAC,iBAAiB,EAAC,OAAO,EAAE,SAAS,gBAAa,YAAY,EAAC,KAAK,EAAE,WAAW,YACzF,iBAAS,GACL,EAET,gCAAK,KAAK,EAAC,iBAAiB,EAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAA,yCAAmB,EAAC,IAAI,CAAC,OAAO,CAAC,EAAE,GAAI,EAEvG,iCAAK,KAAK,EAAC,gBAAgB,aACvB,kCAAM,KAAK,EAAC,kBAAkB,aACzB,SAAS,GAAG,CAAC,UAAM,UAAU,IAC3B,EAEP,iCAAK,KAAK,EAAC,iBAAiB,aACvB,CAAC,WAAW,IAAI,CACb,mCACI,KAAK,EAAC,0CAA0C,EAChD,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,WAAW,qBAGb,CACZ,EACA,cAAc,IAAI,CACf,mCAAQ,KAAK,EAAC,wCAAwC,EAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,YACrF,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GACxB,CACZ,IACC,IACJ,EAEL,CAAC,UAAU,IAAI,CACZ,+BACI,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,SAAS,EACrE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAC5C,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,EACtD,KAAK,EAAC,kBAAkB,EACxB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,yBAEtE,uBAAe,IACxB,CACP,IACF,CACN,CAAA;AACL,CAAC","sourcesContent":["import { h } from 'preact'\nimport { ProductTourStep, ProductTourAppearance } from '../../../posthog-product-tours-types'\nimport { renderTipTapContent } from '../product-tours-utils'\nimport { IconPosthogLogo, cancelSVG } from '../../surveys/icons'\n\nexport interface ProductTourTooltipInnerProps {\n step: ProductTourStep\n appearance?: ProductTourAppearance\n stepIndex: number\n totalSteps: number\n onNext?: () => void\n onPrevious?: () => void\n onDismiss?: () => void\n}\n\nexport function ProductTourTooltipInner({\n step,\n appearance,\n stepIndex,\n totalSteps,\n onNext,\n onPrevious,\n onDismiss,\n}: ProductTourTooltipInnerProps): h.JSX.Element {\n const whiteLabel = appearance?.whiteLabel ?? false\n const isLastStep = stepIndex >= totalSteps - 1\n const isFirstStep = stepIndex === 0\n const showNextButton = step.progressionTrigger === 'button' || step.type === 'modal'\n\n const isInteractive = !!(onNext || onPrevious || onDismiss)\n const cursorStyle = isInteractive ? undefined : { cursor: 'default' }\n\n return (\n <>\n <button class=\"ph-tour-dismiss\" onClick={onDismiss} aria-label=\"Close tour\" style={cursorStyle}>\n {cancelSVG}\n </button>\n\n <div class=\"ph-tour-content\" dangerouslySetInnerHTML={{ __html: renderTipTapContent(step.content) }} />\n\n <div class=\"ph-tour-footer\">\n <span class=\"ph-tour-progress\">\n {stepIndex + 1} of {totalSteps}\n </span>\n\n <div class=\"ph-tour-buttons\">\n {!isFirstStep && (\n <button\n class=\"ph-tour-button ph-tour-button--secondary\"\n onClick={onPrevious}\n style={cursorStyle}\n >\n Back\n </button>\n )}\n {showNextButton && (\n <button class=\"ph-tour-button ph-tour-button--primary\" onClick={onNext} style={cursorStyle}>\n {isLastStep ? 'Done' : 'Next'}\n </button>\n )}\n </div>\n </div>\n\n {!whiteLabel && (\n <a\n href={isInteractive ? 'https://posthog.com/product-tours' : undefined}\n target={isInteractive ? '_blank' : undefined}\n rel={isInteractive ? 'noopener noreferrer' : undefined}\n class=\"ph-tour-branding\"\n style={isInteractive ? undefined : { cursor: 'default', pointerEvents: 'none' }}\n >\n Tour by {IconPosthogLogo}\n </a>\n )}\n </>\n )\n}\n"]}
1
+ {"version":3,"file":"ProductTourTooltipInner.js","sourceRoot":"","sources":["../../../../../src/extensions/product-tours/components/ProductTourTooltipInner.tsx"],"names":[],"mappings":";;AAeA,0DA6DC;;AA1ED,8DAAoD;AACpD,6CAAgE;AAYhE,SAAgB,uBAAuB,CAAC,EAQT;;QAP3B,IAAI,UAAA,EACJ,UAAU,gBAAA,EACV,SAAS,eAAA,EACT,UAAU,gBAAA,EACV,MAAM,YAAA,EACN,UAAU,gBAAA,EACV,SAAS,eAAA;IAET,IAAM,UAAU,GAAG,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,mCAAI,KAAK,CAAA;IAClD,IAAM,UAAU,GAAG,SAAS,IAAI,UAAU,GAAG,CAAC,CAAA;IAC9C,IAAM,WAAW,GAAG,SAAS,KAAK,CAAC,CAAA;IACnC,IAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAA;IAEpF,IAAM,aAAa,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,UAAU,IAAI,SAAS,CAAC,CAAA;IAC3D,IAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;IAErE,OAAO,CACH,6DACI,mCAAQ,KAAK,EAAC,iBAAiB,EAAC,OAAO,EAAE,SAAS,gBAAa,YAAY,EAAC,KAAK,EAAE,WAAW,YACzF,iBAAS,GACL,EAET,gCAAK,KAAK,EAAC,iBAAiB,EAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAA,iCAAW,EAAC,IAAI,CAAC,EAAE,GAAI,EAEvF,iCAAK,KAAK,EAAC,gBAAgB,aACvB,kCAAM,KAAK,EAAC,kBAAkB,aACzB,SAAS,GAAG,CAAC,UAAM,UAAU,IAC3B,EAEP,iCAAK,KAAK,EAAC,iBAAiB,aACvB,CAAC,WAAW,IAAI,CACb,mCACI,KAAK,EAAC,0CAA0C,EAChD,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,WAAW,qBAGb,CACZ,EACA,cAAc,IAAI,CACf,mCAAQ,KAAK,EAAC,wCAAwC,EAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,YACrF,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GACxB,CACZ,IACC,IACJ,EAEL,CAAC,UAAU,IAAI,CACZ,+BACI,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,SAAS,EACrE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAC5C,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,EACtD,KAAK,EAAC,kBAAkB,EACxB,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,yBAEtE,uBAAe,IACxB,CACP,IACF,CACN,CAAA;AACL,CAAC","sourcesContent":["import { h } from 'preact'\nimport { ProductTourStep, ProductTourAppearance } from '../../../posthog-product-tours-types'\nimport { getStepHtml } from '../product-tours-utils'\nimport { IconPosthogLogo, cancelSVG } from '../../surveys/icons'\n\nexport interface ProductTourTooltipInnerProps {\n step: ProductTourStep\n appearance?: ProductTourAppearance\n stepIndex: number\n totalSteps: number\n onNext?: () => void\n onPrevious?: () => void\n onDismiss?: () => void\n}\n\nexport function ProductTourTooltipInner({\n step,\n appearance,\n stepIndex,\n totalSteps,\n onNext,\n onPrevious,\n onDismiss,\n}: ProductTourTooltipInnerProps): h.JSX.Element {\n const whiteLabel = appearance?.whiteLabel ?? false\n const isLastStep = stepIndex >= totalSteps - 1\n const isFirstStep = stepIndex === 0\n const showNextButton = step.progressionTrigger === 'button' || step.type === 'modal'\n\n const isInteractive = !!(onNext || onPrevious || onDismiss)\n const cursorStyle = isInteractive ? undefined : { cursor: 'default' }\n\n return (\n <>\n <button class=\"ph-tour-dismiss\" onClick={onDismiss} aria-label=\"Close tour\" style={cursorStyle}>\n {cancelSVG}\n </button>\n\n <div class=\"ph-tour-content\" dangerouslySetInnerHTML={{ __html: getStepHtml(step) }} />\n\n <div class=\"ph-tour-footer\">\n <span class=\"ph-tour-progress\">\n {stepIndex + 1} of {totalSteps}\n </span>\n\n <div class=\"ph-tour-buttons\">\n {!isFirstStep && (\n <button\n class=\"ph-tour-button ph-tour-button--secondary\"\n onClick={onPrevious}\n style={cursorStyle}\n >\n Back\n </button>\n )}\n {showNextButton && (\n <button class=\"ph-tour-button ph-tour-button--primary\" onClick={onNext} style={cursorStyle}>\n {isLastStep ? 'Done' : 'Next'}\n </button>\n )}\n </div>\n </div>\n\n {!whiteLabel && (\n <a\n href={isInteractive ? 'https://posthog.com/product-tours' : undefined}\n target={isInteractive ? '_blank' : undefined}\n rel={isInteractive ? 'noopener noreferrer' : undefined}\n class=\"ph-tour-branding\"\n style={isInteractive ? undefined : { cursor: 'default', pointerEvents: 'none' }}\n >\n Tour by {IconPosthogLogo}\n </a>\n )}\n </>\n )\n}\n"]}
@@ -0,0 +1,30 @@
1
+ export declare function elementIsVisible(element: HTMLElement, cache: WeakMap<HTMLElement, boolean>): boolean;
2
+ export interface SelectorGroup {
3
+ cardinality: number;
4
+ cssSelectors: Array<{
5
+ css: string;
6
+ offset: number;
7
+ }>;
8
+ }
9
+ export interface AutoData {
10
+ notextGroups: SelectorGroup[];
11
+ textGroups: SelectorGroup[];
12
+ }
13
+ export interface InferredSelector {
14
+ autoData: string;
15
+ text: string | null;
16
+ excludeText?: boolean;
17
+ }
18
+ /**
19
+ * if inferSelector is the sauce, this is the nugget
20
+ *
21
+ * find an element in the dom using the element inference data
22
+ *
23
+ * 1. try each group of selectors, starting with most specific (lowest cardinality)
24
+ * 2. try each selector in the group - run the css query, go to offset
25
+ * 3. "vote" for the element if it was found
26
+ * 4. return early if any element gets majority votes
27
+ * 5. return element w/ most votes
28
+ */
29
+ export declare function findElement(selector: InferredSelector): HTMLElement | null;
30
+ export declare function getElementPath(el: HTMLElement | null, depth?: number): string | null;