posthog-js 1.321.2 → 1.321.3
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/dist/array.full.es5.js +1 -1
- package/dist/array.full.js +1 -1
- package/dist/array.full.no-external.js +1 -1
- package/dist/array.js +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/customizations.full.js +1 -1
- package/dist/lazy-recorder.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +1 -0
- package/dist/module.full.d.ts +1 -0
- package/dist/module.full.js +1 -1
- package/dist/module.full.js.map +1 -1
- package/dist/module.full.no-external.d.ts +1 -0
- package/dist/module.full.no-external.js +1 -1
- package/dist/module.full.no-external.js.map +1 -1
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +1 -0
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/posthog-recorder.js +1 -1
- package/dist/product-tours-preview.d.ts +1 -0
- package/dist/product-tours-preview.js +1 -1
- package/dist/product-tours-preview.js.map +1 -1
- package/dist/product-tours.js +1 -1
- package/dist/product-tours.js.map +1 -1
- package/dist/src/extensions/product-tours/product-tours-utils.d.ts +9 -3
- package/dist/src/posthog-product-tours-types.d.ts +1 -0
- package/dist/surveys-preview.d.ts +1 -0
- package/lib/package.json +1 -1
- package/lib/src/extensions/product-tours/components/ProductTourTooltip.js +37 -14
- package/lib/src/extensions/product-tours/components/ProductTourTooltip.js.map +1 -1
- package/lib/src/extensions/product-tours/product-tours-utils.d.ts +9 -3
- package/lib/src/extensions/product-tours/product-tours-utils.js +13 -24
- package/lib/src/extensions/product-tours/product-tours-utils.js.map +1 -1
- package/lib/src/posthog-product-tours-types.d.ts +1 -0
- package/lib/src/posthog-product-tours-types.js +1 -0
- package/lib/src/posthog-product-tours-types.js.map +1 -1
- package/package.json +2 -2
|
@@ -15,11 +15,17 @@ export declare function getElementMetadata(element: HTMLElement): {
|
|
|
15
15
|
};
|
|
16
16
|
export type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
|
|
17
17
|
export interface PositionResult {
|
|
18
|
-
top: number;
|
|
19
|
-
left: number;
|
|
20
18
|
position: TooltipPosition;
|
|
19
|
+
top?: number;
|
|
20
|
+
bottom?: number;
|
|
21
|
+
left?: number;
|
|
22
|
+
right?: number;
|
|
21
23
|
}
|
|
22
|
-
export
|
|
24
|
+
export interface TooltipDimensions {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function calculateTooltipPosition(targetRect: DOMRect, tooltipDimensions: TooltipDimensions): PositionResult;
|
|
23
29
|
export declare function getSpotlightStyle(targetRect: DOMRect, padding?: number): Record<string, string>;
|
|
24
30
|
export declare function addProductTourCSSVariablesToElement(element: HTMLElement, appearance?: ProductTourAppearance): void;
|
|
25
31
|
export declare function renderTipTapContent(content: any): string;
|
|
@@ -101,6 +101,7 @@ export interface ProductTourAppearance {
|
|
|
101
101
|
whiteLabel?: boolean;
|
|
102
102
|
/** defaults to true, auto-set to false for announcements/banners */
|
|
103
103
|
dismissOnClickOutside?: boolean;
|
|
104
|
+
zIndex?: number;
|
|
104
105
|
}
|
|
105
106
|
export interface ProductTour {
|
|
106
107
|
id: string;
|
|
@@ -1720,6 +1720,7 @@ interface ProductTourAppearance {
|
|
|
1720
1720
|
whiteLabel?: boolean;
|
|
1721
1721
|
/** defaults to true, auto-set to false for announcements/banners */
|
|
1722
1722
|
dismissOnClickOutside?: boolean;
|
|
1723
|
+
zIndex?: number;
|
|
1723
1724
|
}
|
|
1724
1725
|
interface ProductTour {
|
|
1725
1726
|
id: string;
|
package/lib/package.json
CHANGED
|
@@ -37,7 +37,6 @@ var utils_1 = require("../../../utils");
|
|
|
37
37
|
var globals_1 = require("../../../utils/globals");
|
|
38
38
|
var ProductTourTooltipInner_1 = require("./ProductTourTooltipInner");
|
|
39
39
|
var ProductTourSurveyStepInner_1 = require("./ProductTourSurveyStepInner");
|
|
40
|
-
var core_2 = require("@posthog/core");
|
|
41
40
|
var window = globals_1.window;
|
|
42
41
|
function getOppositePosition(position) {
|
|
43
42
|
var opposites = {
|
|
@@ -99,19 +98,32 @@ function ProductTourTooltip(_a) {
|
|
|
99
98
|
var _c = __read((0, hooks_1.useState)('entering'), 2), transitionState = _c[0], setTransitionState = _c[1];
|
|
100
99
|
var _d = __read((0, hooks_1.useState)(null), 2), position = _d[0], setPosition = _d[1];
|
|
101
100
|
var _e = __read((0, hooks_1.useState)(null), 2), spotlightStyle = _e[0], setSpotlightStyle = _e[1];
|
|
102
|
-
var _f = __read((0, hooks_1.useState)(
|
|
103
|
-
var _g = __read((0, hooks_1.useState)(
|
|
101
|
+
var _f = __read((0, hooks_1.useState)(false), 2), isMeasured = _f[0], setIsMeasured = _f[1];
|
|
102
|
+
var _g = __read((0, hooks_1.useState)(step), 2), displayedStep = _g[0], setDisplayedStep = _g[1];
|
|
103
|
+
var _h = __read((0, hooks_1.useState)(stepIndex), 2), displayedStepIndex = _h[0], setDisplayedStepIndex = _h[1];
|
|
104
|
+
var tooltipRef = (0, hooks_1.useRef)(null);
|
|
104
105
|
var previousStepRef = (0, hooks_1.useRef)(stepIndex);
|
|
105
106
|
var isTransitioningRef = (0, hooks_1.useRef)(false);
|
|
106
107
|
// Modal and survey steps use screen positioning (not anchored to an element)
|
|
107
108
|
var isScreenPositioned = displayedStep.type === 'modal' || displayedStep.type === 'survey';
|
|
108
109
|
var updatePosition = (0, hooks_1.useCallback)(function () {
|
|
109
|
-
if (!targetElement)
|
|
110
|
+
if (!targetElement || !tooltipRef.current)
|
|
110
111
|
return;
|
|
111
|
-
var
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
var tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
113
|
+
var tooltipDimensions = {
|
|
114
|
+
width: tooltipRect.width,
|
|
115
|
+
height: tooltipRect.height,
|
|
116
|
+
};
|
|
117
|
+
var targetRect = targetElement.getBoundingClientRect();
|
|
118
|
+
setPosition((0, product_tours_utils_1.calculateTooltipPosition)(targetRect, tooltipDimensions));
|
|
119
|
+
setSpotlightStyle((0, product_tours_utils_1.getSpotlightStyle)(targetRect));
|
|
120
|
+
setIsMeasured(true);
|
|
114
121
|
}, [targetElement]);
|
|
122
|
+
(0, hooks_1.useLayoutEffect)(function () {
|
|
123
|
+
if (!isScreenPositioned && !isMeasured && tooltipRef.current && targetElement) {
|
|
124
|
+
updatePosition();
|
|
125
|
+
}
|
|
126
|
+
}, [isScreenPositioned, isMeasured, targetElement, updatePosition]);
|
|
115
127
|
(0, hooks_1.useEffect)(function () {
|
|
116
128
|
var currentStepIndex = stepIndex;
|
|
117
129
|
var isStepChange = previousStepRef.current !== stepIndex;
|
|
@@ -151,6 +163,7 @@ function ProductTourTooltip(_a) {
|
|
|
151
163
|
if (step.type === 'element') {
|
|
152
164
|
setPosition(null);
|
|
153
165
|
setSpotlightStyle(null);
|
|
166
|
+
setIsMeasured(false);
|
|
154
167
|
}
|
|
155
168
|
setDisplayedStep(step);
|
|
156
169
|
setDisplayedStepIndex(stepIndex);
|
|
@@ -200,8 +213,8 @@ function ProductTourTooltip(_a) {
|
|
|
200
213
|
};
|
|
201
214
|
var isVisible = transitionState === 'visible';
|
|
202
215
|
var isSurvey = displayedStep.type === 'survey';
|
|
203
|
-
// For element steps,
|
|
204
|
-
var isPositionReady = isScreenPositioned ||
|
|
216
|
+
// For element steps, position is ready once we've measured and calculated
|
|
217
|
+
var isPositionReady = isScreenPositioned || isMeasured;
|
|
205
218
|
var basePosition = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto', transform: 'none' };
|
|
206
219
|
// surveys default to bottom: 0, and PT should not, so this is a little clunky
|
|
207
220
|
var getModalPosition = function () {
|
|
@@ -212,14 +225,24 @@ function ProductTourTooltip(_a) {
|
|
|
212
225
|
}
|
|
213
226
|
return pos;
|
|
214
227
|
};
|
|
228
|
+
var getElementPositionStyle = function () {
|
|
229
|
+
if (!position) {
|
|
230
|
+
return {};
|
|
231
|
+
}
|
|
232
|
+
var isHorizontal = position.position === 'left' || position.position === 'right';
|
|
233
|
+
return {
|
|
234
|
+
top: !(0, core_1.isUndefined)(position.top) ? "".concat(position.top, "px") : 'auto',
|
|
235
|
+
bottom: !(0, core_1.isUndefined)(position.bottom) ? "".concat(position.bottom, "px") : 'auto',
|
|
236
|
+
left: !(0, core_1.isUndefined)(position.left) ? "".concat(position.left, "px") : 'auto',
|
|
237
|
+
right: !(0, core_1.isUndefined)(position.right) ? "".concat(position.right, "px") : 'auto',
|
|
238
|
+
transform: isHorizontal ? 'translateY(-50%)' : 'translateX(-50%)',
|
|
239
|
+
};
|
|
240
|
+
};
|
|
215
241
|
var tooltipStyle = __assign(__assign({}, (displayedStep.maxWidth && {
|
|
216
242
|
width: "".concat(displayedStep.maxWidth, "px"),
|
|
217
243
|
maxWidth: "".concat(displayedStep.maxWidth, "px"),
|
|
218
244
|
})), (isScreenPositioned
|
|
219
|
-
? __assign(__assign({}, basePosition), getModalPosition()) :
|
|
220
|
-
top: position ? "".concat(position.top, "px") : '0',
|
|
221
|
-
left: position ? "".concat(position.left, "px") : '0',
|
|
222
|
-
}));
|
|
245
|
+
? __assign(__assign({}, basePosition), getModalPosition()) : getElementPositionStyle()));
|
|
223
246
|
return ((0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-container", children: [((_b = tour.appearance) === null || _b === void 0 ? void 0 : _b.dismissOnClickOutside) !== false && ((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: {
|
|
224
247
|
opacity: isScreenPositioned && isVisible ? 1 : 0,
|
|
225
248
|
transition: "opacity ".concat(TRANSITION_DURATION, "ms ease-out"),
|
|
@@ -232,6 +255,6 @@ function ProductTourTooltip(_a) {
|
|
|
232
255
|
cursor: 'pointer',
|
|
233
256
|
})), onClick: displayedStep.progressionTrigger === 'click' && !isScreenPositioned
|
|
234
257
|
? handleSpotlightClick
|
|
235
|
-
: undefined }), (0, jsx_runtime_1.jsxs)("div", { class: "ph-tour-tooltip ".concat(isScreenPositioned ? 'ph-tour-tooltip--modal' : '', " ").concat(isSurvey ? 'ph-tour-survey-step' : ''), style: __assign(__assign({}, tooltipStyle), { opacity: isVisible && isPositionReady ? 1 : 0, transition: "opacity ".concat(TRANSITION_DURATION, "ms ease-out") }), onClick: handleTooltipClick, children: [!isScreenPositioned && position && ((0, jsx_runtime_1.jsx)("div", { class: "ph-tour-arrow ph-tour-arrow--".concat(getOppositePosition(position.position)) })), isSurvey ? ((0, jsx_runtime_1.jsx)(ProductTourSurveyStepInner_1.ProductTourSurveyStepInner, { step: displayedStep, appearance: tour.appearance, stepIndex: displayedStepIndex, totalSteps: totalSteps, onSubmit: onSurveySubmit, onPrevious: onPrevious, onDismiss: function () { return onDismiss('user_clicked_skip'); } })) : ((0, jsx_runtime_1.jsx)(ProductTourTooltipInner_1.ProductTourTooltipInner, { step: displayedStep, appearance: tour.appearance, stepIndex: displayedStepIndex, totalSteps: totalSteps, onNext: onNext, onPrevious: onPrevious, onDismiss: function () { return onDismiss('user_clicked_skip'); }, onButtonClick: onButtonClick }))] })] }));
|
|
258
|
+
: undefined }), (0, jsx_runtime_1.jsxs)("div", { ref: tooltipRef, class: "ph-tour-tooltip ".concat(isScreenPositioned ? 'ph-tour-tooltip--modal' : '', " ").concat(isSurvey ? 'ph-tour-survey-step' : ''), style: __assign(__assign({}, tooltipStyle), { opacity: isVisible && isPositionReady ? 1 : 0, transition: "opacity ".concat(TRANSITION_DURATION, "ms ease-out") }), onClick: handleTooltipClick, children: [!isScreenPositioned && position && ((0, jsx_runtime_1.jsx)("div", { class: "ph-tour-arrow ph-tour-arrow--".concat(getOppositePosition(position.position)) })), isSurvey ? ((0, jsx_runtime_1.jsx)(ProductTourSurveyStepInner_1.ProductTourSurveyStepInner, { step: displayedStep, appearance: tour.appearance, stepIndex: displayedStepIndex, totalSteps: totalSteps, onSubmit: onSurveySubmit, onPrevious: onPrevious, onDismiss: function () { return onDismiss('user_clicked_skip'); } })) : ((0, jsx_runtime_1.jsx)(ProductTourTooltipInner_1.ProductTourTooltipInner, { step: displayedStep, appearance: tour.appearance, stepIndex: displayedStepIndex, totalSteps: totalSteps, onNext: onNext, onPrevious: onPrevious, onDismiss: function () { return onDismiss('user_clicked_skip'); }, onButtonClick: onButtonClick }))] })] }));
|
|
236
259
|
}
|
|
237
260
|
//# sourceMappingURL=ProductTourTooltip.js.map
|
|
@@ -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 {\n ProductTour,\n ProductTourStep,\n ProductTourDismissReason,\n ProductTourStepButton,\n} from '../../../posthog-product-tours-types'\nimport { SurveyPosition } from '@posthog/core'\nimport { calculateTooltipPosition, getSpotlightStyle, TooltipPosition } from '../product-tours-utils'\nimport { getPopoverPosition } from '../../surveys/surveys-extension-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 onButtonClick?: (button: ProductTourStepButton) => 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 onButtonClick,\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 use screen positioning (not anchored to an element)\n const isScreenPositioned = 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' || isScreenPositioned) 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, isScreenPositioned])\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 = isScreenPositioned || !isNull(position)\n\n const basePosition = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto', transform: 'none' }\n\n // surveys default to bottom: 0, and PT should not, so this is a little clunky\n const getModalPosition = () => {\n const pos = getPopoverPosition(undefined, displayedStep.modalPosition ?? SurveyPosition.MiddleCenter)\n if (!('top' in pos) && !('bottom' in pos)) {\n return { ...pos, bottom: '30px' }\n }\n return pos\n }\n\n const tooltipStyle = {\n ...(displayedStep.maxWidth && {\n width: `${displayedStep.maxWidth}px`,\n maxWidth: `${displayedStep.maxWidth}px`,\n }),\n ...(isScreenPositioned\n ? {\n ...basePosition,\n ...getModalPosition(),\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 {tour.appearance?.dismissOnClickOutside !== false && (\n <div class=\"ph-tour-click-overlay\" onClick={handleOverlayClick} />\n )}\n\n {/* Modal overlay - visible for non-element steps */}\n <div\n class=\"ph-tour-modal-overlay\"\n style={{\n opacity: isScreenPositioned && isVisible ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n pointerEvents: '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: !isScreenPositioned && isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n ...(displayedStep.progressionTrigger === 'click' &&\n !isScreenPositioned && {\n pointerEvents: 'auto',\n cursor: 'pointer',\n }),\n }}\n onClick={\n displayedStep.progressionTrigger === 'click' && !isScreenPositioned\n ? handleSpotlightClick\n : undefined\n }\n />\n\n <div\n class={`ph-tour-tooltip ${isScreenPositioned ? '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 {!isScreenPositioned && 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 onButtonClick={onButtonClick}\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, useLayoutEffect, useState, useCallback, useRef } from 'preact/hooks'\nimport {\n ProductTour,\n ProductTourStep,\n ProductTourDismissReason,\n ProductTourStepButton,\n} from '../../../posthog-product-tours-types'\nimport { isUndefined, SurveyPosition } from '@posthog/core'\nimport { calculateTooltipPosition, getSpotlightStyle, TooltipPosition, TooltipDimensions } from '../product-tours-utils'\nimport { getPopoverPosition } from '../../surveys/surveys-extension-utils'\nimport { addEventListener } from '../../../utils'\nimport { window as _window } from '../../../utils/globals'\nimport { ProductTourTooltipInner } from './ProductTourTooltipInner'\nimport { ProductTourSurveyStepInner } from './ProductTourSurveyStepInner'\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 onButtonClick?: (button: ProductTourStepButton) => 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 onButtonClick,\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 const [isMeasured, setIsMeasured] = useState(false)\n\n const [displayedStep, setDisplayedStep] = useState(step)\n const [displayedStepIndex, setDisplayedStepIndex] = useState(stepIndex)\n\n const tooltipRef = useRef<HTMLDivElement>(null)\n const previousStepRef = useRef(stepIndex)\n const isTransitioningRef = useRef(false)\n\n // Modal and survey steps use screen positioning (not anchored to an element)\n const isScreenPositioned = displayedStep.type === 'modal' || displayedStep.type === 'survey'\n\n const updatePosition = useCallback(() => {\n if (!targetElement || !tooltipRef.current) return\n\n const tooltipRect = tooltipRef.current.getBoundingClientRect()\n const tooltipDimensions: TooltipDimensions = {\n width: tooltipRect.width,\n height: tooltipRect.height,\n }\n\n const targetRect = targetElement.getBoundingClientRect()\n setPosition(calculateTooltipPosition(targetRect, tooltipDimensions))\n setSpotlightStyle(getSpotlightStyle(targetRect))\n setIsMeasured(true)\n }, [targetElement])\n\n useLayoutEffect(() => {\n if (!isScreenPositioned && !isMeasured && tooltipRef.current && targetElement) {\n updatePosition()\n }\n }, [isScreenPositioned, isMeasured, targetElement, updatePosition])\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 setIsMeasured(false)\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' || isScreenPositioned) 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, isScreenPositioned])\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, position is ready once we've measured and calculated\n const isPositionReady = isScreenPositioned || isMeasured\n\n const basePosition = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto', transform: 'none' }\n\n // surveys default to bottom: 0, and PT should not, so this is a little clunky\n const getModalPosition = () => {\n const pos = getPopoverPosition(undefined, displayedStep.modalPosition ?? SurveyPosition.MiddleCenter)\n if (!('top' in pos) && !('bottom' in pos)) {\n return { ...pos, bottom: '30px' }\n }\n return pos\n }\n\n const getElementPositionStyle = (): Record<string, string> => {\n if (!position) {\n return {}\n }\n\n const isHorizontal = position.position === 'left' || position.position === 'right'\n\n return {\n top: !isUndefined(position.top) ? `${position.top}px` : 'auto',\n bottom: !isUndefined(position.bottom) ? `${position.bottom}px` : 'auto',\n left: !isUndefined(position.left) ? `${position.left}px` : 'auto',\n right: !isUndefined(position.right) ? `${position.right}px` : 'auto',\n transform: isHorizontal ? 'translateY(-50%)' : 'translateX(-50%)',\n }\n }\n\n const tooltipStyle = {\n ...(displayedStep.maxWidth && {\n width: `${displayedStep.maxWidth}px`,\n maxWidth: `${displayedStep.maxWidth}px`,\n }),\n ...(isScreenPositioned\n ? {\n ...basePosition,\n ...getModalPosition(),\n }\n : getElementPositionStyle()),\n }\n\n return (\n <div class=\"ph-tour-container\">\n {tour.appearance?.dismissOnClickOutside !== false && (\n <div class=\"ph-tour-click-overlay\" onClick={handleOverlayClick} />\n )}\n\n {/* Modal overlay - visible for non-element steps */}\n <div\n class=\"ph-tour-modal-overlay\"\n style={{\n opacity: isScreenPositioned && isVisible ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n pointerEvents: '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: !isScreenPositioned && isVisible && isPositionReady ? 1 : 0,\n transition: `opacity ${TRANSITION_DURATION}ms ease-out`,\n ...(displayedStep.progressionTrigger === 'click' &&\n !isScreenPositioned && {\n pointerEvents: 'auto',\n cursor: 'pointer',\n }),\n }}\n onClick={\n displayedStep.progressionTrigger === 'click' && !isScreenPositioned\n ? handleSpotlightClick\n : undefined\n }\n />\n\n <div\n ref={tooltipRef}\n class={`ph-tour-tooltip ${isScreenPositioned ? '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 {!isScreenPositioned && 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 onButtonClick={onButtonClick}\n />\n )}\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -15,11 +15,17 @@ export declare function getElementMetadata(element: HTMLElement): {
|
|
|
15
15
|
};
|
|
16
16
|
export type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
|
|
17
17
|
export interface PositionResult {
|
|
18
|
-
top: number;
|
|
19
|
-
left: number;
|
|
20
18
|
position: TooltipPosition;
|
|
19
|
+
top?: number;
|
|
20
|
+
bottom?: number;
|
|
21
|
+
left?: number;
|
|
22
|
+
right?: number;
|
|
21
23
|
}
|
|
22
|
-
export
|
|
24
|
+
export interface TooltipDimensions {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function calculateTooltipPosition(targetRect: DOMRect, tooltipDimensions: TooltipDimensions): PositionResult;
|
|
23
29
|
export declare function getSpotlightStyle(targetRect: DOMRect, padding?: number): Record<string, string>;
|
|
24
30
|
export declare function addProductTourCSSVariablesToElement(element: HTMLElement, appearance?: ProductTourAppearance): void;
|
|
25
31
|
export declare function renderTipTapContent(content: any): string;
|
|
@@ -88,38 +88,26 @@ function getElementMetadata(element) {
|
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
var TOOLTIP_MARGIN = 12;
|
|
91
|
-
|
|
92
|
-
var TOOLTIP_HEIGHT_ESTIMATE = 180;
|
|
93
|
-
function calculateTooltipPosition(targetRect) {
|
|
91
|
+
function calculateTooltipPosition(targetRect, tooltipDimensions) {
|
|
94
92
|
var viewportWidth = window.innerWidth;
|
|
95
93
|
var viewportHeight = window.innerHeight;
|
|
94
|
+
var width = tooltipDimensions.width, height = tooltipDimensions.height;
|
|
95
|
+
var spaceAbove = targetRect.top;
|
|
96
96
|
var spaceBelow = viewportHeight - targetRect.bottom;
|
|
97
97
|
var spaceLeft = targetRect.left;
|
|
98
98
|
var spaceRight = viewportWidth - targetRect.right;
|
|
99
|
-
var
|
|
100
|
-
var
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
position = 'right';
|
|
104
|
-
top = targetRect.top + targetRect.height / 2 - TOOLTIP_HEIGHT_ESTIMATE / 2;
|
|
105
|
-
left = targetRect.right + TOOLTIP_MARGIN;
|
|
99
|
+
var targetCenterY = targetRect.top + targetRect.height / 2;
|
|
100
|
+
var targetCenterX = targetRect.left + targetRect.width / 2;
|
|
101
|
+
if (spaceRight >= width + TOOLTIP_MARGIN) {
|
|
102
|
+
return { position: 'right', top: targetCenterY, left: targetRect.right + TOOLTIP_MARGIN };
|
|
106
103
|
}
|
|
107
|
-
|
|
108
|
-
position
|
|
109
|
-
top = targetRect.top + targetRect.height / 2 - TOOLTIP_HEIGHT_ESTIMATE / 2;
|
|
110
|
-
left = targetRect.left - TOOLTIP_WIDTH - TOOLTIP_MARGIN;
|
|
104
|
+
if (spaceLeft >= width + TOOLTIP_MARGIN) {
|
|
105
|
+
return { position: 'left', top: targetCenterY, right: viewportWidth - targetRect.left + TOOLTIP_MARGIN };
|
|
111
106
|
}
|
|
112
|
-
|
|
113
|
-
position
|
|
114
|
-
top = targetRect.bottom + TOOLTIP_MARGIN;
|
|
115
|
-
left = targetRect.left + targetRect.width / 2 - TOOLTIP_WIDTH / 2;
|
|
107
|
+
if (spaceAbove >= height + TOOLTIP_MARGIN && spaceBelow < height + TOOLTIP_MARGIN) {
|
|
108
|
+
return { position: 'top', bottom: viewportHeight - targetRect.top + TOOLTIP_MARGIN, left: targetCenterX };
|
|
116
109
|
}
|
|
117
|
-
|
|
118
|
-
position = 'top';
|
|
119
|
-
top = targetRect.top - TOOLTIP_HEIGHT_ESTIMATE - TOOLTIP_MARGIN;
|
|
120
|
-
left = targetRect.left + targetRect.width / 2 - TOOLTIP_WIDTH / 2;
|
|
121
|
-
}
|
|
122
|
-
return { top: top, left: left, position: position };
|
|
110
|
+
return { position: 'bottom', top: targetRect.bottom + TOOLTIP_MARGIN, left: targetCenterX };
|
|
123
111
|
}
|
|
124
112
|
function getSpotlightStyle(targetRect, padding) {
|
|
125
113
|
if (padding === void 0) { padding = 8; }
|
|
@@ -147,6 +135,7 @@ function addProductTourCSSVariablesToElement(element, appearance) {
|
|
|
147
135
|
style.setProperty('--ph-tour-button-text-color', (0, surveys_extension_utils_1.getContrastingTextColor)(merged.buttonColor));
|
|
148
136
|
style.setProperty('--ph-tour-box-shadow', merged.boxShadow);
|
|
149
137
|
style.setProperty('--ph-tour-overlay-color', merged.showOverlay ? 'rgba(0, 0, 0, 0.5)' : 'transparent');
|
|
138
|
+
style.setProperty('--ph-tour-z-index', String(merged.zIndex));
|
|
150
139
|
// Internal styling variables (not customizable)
|
|
151
140
|
style.setProperty('--ph-tour-button-secondary-color', 'transparent');
|
|
152
141
|
style.setProperty('--ph-tour-button-secondary-text-color', merged.textColor);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-tours-utils.js","sourceRoot":"","sources":["../../../../src/extensions/product-tours/product-tours-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,4DAIC;AAQD,sDAsBC;AAED,4CAaC;AAED,gDAYC;AAcD,4DA+BC;AAED,8CAOC;AAED,kFAyBC;AAED,kDAwDC;AAED,oCAEC;AAQD,kCAUC;AAjPD,wDAAiC;AAEjC,iFAK0C;AAC1C,gEAA8D;AAC9D,+CAA8E;AAC9E,8EAAsG;AAEtG,wEAAkD;AAElD,IAAM,QAAQ,GAAG,kBAAqB,CAAA;AACtC,IAAM,MAAM,GAAG,gBAAqC,CAAA;AAEpD,SAAgB,wBAAwB;IACpC,IAAM,UAAU,GAAG,IAAA,qCAAiB,EAAC,QAAQ,EAAE,OAAO,0BAAiB,KAAK,QAAQ,CAAC,CAAC,CAAC,0BAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC9G,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,YAAY,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAA;IAC9D,OAAO,UAAU,CAAA;AACrB,CAAC;AAQD,SAAgB,qBAAqB,CAAC,QAAgB;IAClD,IAAI,CAAC;QACD,IAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;QAEpD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;QAC/D,CAAC;QAED,IAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAgB,CAAA;QAE1C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;QAC/E,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,OAAO,EAAE,OAAO,SAAA,EAAE,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAA;QAC9E,CAAC;QAED,OAAO,EAAE,OAAO,SAAA,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;IAClD,CAAC;IAAC,WAAM,CAAC;QACL,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;IAC/D,CAAC;AACL,CAAC;AAED,SAAgB,gBAAgB,CAAC,OAAoB;IACjD,IAAM,KAAK,GAAG,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAE9C,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,KAAK,GAAG,EAAE,CAAC;QACrF,OAAO,KAAK,CAAA;IAChB,CAAC;IAED,IAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAA;IAC5C,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,CAAA;IAChB,CAAC;IAED,OAAO,IAAI,CAAA;AACf,CAAC;AAED,SAAgB,kBAAkB,CAAC,OAAoB;;IAMnD,OAAO;QACH,GAAG,EAAE,OAAO,CAAC,OAAO;QACpB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,SAAS;QAC3B,OAAO,EAAE,OAAO,CAAC,SAAS,IAAI,SAAS;QACvC,IAAI,EAAE,CAAA,MAAA,OAAO,CAAC,SAAS,0CAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAI,SAAS;KACtD,CAAA;AACL,CAAC;AAUD,IAAM,cAAc,GAAG,EAAE,CAAA;AACzB,IAAM,aAAa,GAAG,GAAG,CAAA;AACzB,IAAM,uBAAuB,GAAG,GAAG,CAAA;AAEnC,SAAgB,wBAAwB,CAAC,UAAmB;IACxD,IAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAA;IACvC,IAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAA;IAEzC,IAAM,UAAU,GAAG,cAAc,GAAG,UAAU,CAAC,MAAM,CAAA;IACrD,IAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAA;IACjC,IAAM,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC,KAAK,CAAA;IAEnD,IAAI,QAAyB,CAAA;IAC7B,IAAI,GAAW,CAAA;IACf,IAAI,IAAY,CAAA;IAEhB,IAAI,UAAU,IAAI,aAAa,GAAG,cAAc,EAAE,CAAC;QAC/C,QAAQ,GAAG,OAAO,CAAA;QAClB,GAAG,GAAG,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,uBAAuB,GAAG,CAAC,CAAA;QAC1E,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,cAAc,CAAA;IAC5C,CAAC;SAAM,IAAI,SAAS,IAAI,aAAa,GAAG,cAAc,EAAE,CAAC;QACrD,QAAQ,GAAG,MAAM,CAAA;QACjB,GAAG,GAAG,UAAU,CAAC,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,uBAAuB,GAAG,CAAC,CAAA;QAC1E,IAAI,GAAG,UAAU,CAAC,IAAI,GAAG,aAAa,GAAG,cAAc,CAAA;IAC3D,CAAC;SAAM,IAAI,UAAU,IAAI,uBAAuB,GAAG,cAAc,EAAE,CAAC;QAChE,QAAQ,GAAG,QAAQ,CAAA;QACnB,GAAG,GAAG,UAAU,CAAC,MAAM,GAAG,cAAc,CAAA;QACxC,IAAI,GAAG,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,aAAa,GAAG,CAAC,CAAA;IACrE,CAAC;SAAM,CAAC;QACJ,QAAQ,GAAG,KAAK,CAAA;QAChB,GAAG,GAAG,UAAU,CAAC,GAAG,GAAG,uBAAuB,GAAG,cAAc,CAAA;QAC/D,IAAI,GAAG,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,GAAG,CAAC,GAAG,aAAa,GAAG,CAAC,CAAA;IACrE,CAAC;IAED,OAAO,EAAE,GAAG,KAAA,EAAE,IAAI,MAAA,EAAE,QAAQ,UAAA,EAAE,CAAA;AAClC,CAAC;AAED,SAAgB,iBAAiB,CAAC,UAAmB,EAAE,OAAmB;IAAnB,wBAAA,EAAA,WAAmB;IACtE,OAAO;QACH,GAAG,EAAE,UAAG,UAAU,CAAC,GAAG,GAAG,OAAO,OAAI;QACpC,IAAI,EAAE,UAAG,UAAU,CAAC,IAAI,GAAG,OAAO,OAAI;QACtC,KAAK,EAAE,UAAG,UAAU,CAAC,KAAK,GAAG,OAAO,GAAG,CAAC,OAAI;QAC5C,MAAM,EAAE,UAAG,UAAU,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,OAAI;KACjD,CAAA;AACL,CAAC;AAED,SAAgB,mCAAmC,CAAC,OAAoB,EAAE,UAAkC;IACxG,IAAM,MAAM,yBAAQ,6DAA+B,GAAK,UAAU,CAAE,CAAA;IACpE,IAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;IAE3B,8BAA8B;IAC9B,KAAK,CAAC,WAAW,CAAC,4BAA4B,EAAE,MAAM,CAAC,eAAe,CAAC,CAAA;IACvE,KAAK,CAAC,WAAW,CAAC,sBAAsB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IAC3D,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IAC/D,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,UAAG,MAAM,CAAC,YAAY,OAAI,CAAC,CAAA;IACxE,KAAK,CAAC,WAAW,CAAC,gCAAgC,EAAE,UAAG,MAAM,CAAC,kBAAkB,OAAI,CAAC,CAAA;IACrF,KAAK,CAAC,WAAW,CAAC,wBAAwB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;IAC/D,KAAK,CAAC,WAAW,CAAC,uBAAuB,EAAE,IAAA,uCAAa,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;IAE5E,iBAAiB;IACjB,KAAK,CAAC,WAAW,CAAC,gCAAgC,EAAE,IAAA,mCAAS,EAAC,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAA;IACrF,KAAK,CAAC,WAAW,CAAC,+BAA+B,EAAE,IAAA,iDAAuB,EAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAA;IACnG,KAAK,CAAC,WAAW,CAAC,6BAA6B,EAAE,IAAA,iDAAuB,EAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAA;IAC7F,KAAK,CAAC,WAAW,CAAC,sBAAsB,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IAC3D,KAAK,CAAC,WAAW,CAAC,yBAAyB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAA;IAEvG,gDAAgD;IAChD,KAAK,CAAC,WAAW,CAAC,kCAAkC,EAAE,aAAa,CAAC,CAAA;IACpE,KAAK,CAAC,WAAW,CAAC,uCAAuC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IAC5E,KAAK,CAAC,WAAW,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAA;IACjD,KAAK,CAAC,WAAW,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA;AAClD,CAAC;AAED,SAAgB,mBAAmB,CAAC,OAAY;;;IAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,EAAE,CAAA;IACb,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QAEzC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;;gBAChB,KAAmB,IAAA,KAAA,SAAA,OAAO,CAAC,KAAK,CAAA,gBAAA,4BAAE,CAAC;oBAA9B,IAAM,IAAI,WAAA;oBACX,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;wBAChB,KAAK,MAAM;4BACP,IAAI,GAAG,kBAAW,IAAI,cAAW,CAAA;4BACjC,MAAK;wBACT,KAAK,QAAQ;4BACT,IAAI,GAAG,cAAO,IAAI,UAAO,CAAA;4BACzB,MAAK;wBACT,KAAK,WAAW;4BACZ,IAAI,GAAG,aAAM,IAAI,SAAM,CAAA;4BACvB,MAAK;wBACT,KAAK,QAAQ;4BACT,IAAI,GAAG,aAAM,IAAI,SAAM,CAAA;4BACvB,MAAK;oBACb,CAAC;gBACL,CAAC;;;;;;;;;QACL,CAAC;QAED,OAAO,IAAI,CAAA;IACf,CAAC;IAED,IAAM,QAAQ,GAAG,CAAA,MAAA,OAAO,CAAC,OAAO,0CAAE,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,EAAE,CAAC,KAAI,EAAE,CAAA;IAEzE,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,KAAK;YACN,OAAO,QAAQ,CAAA;QACnB,KAAK,WAAW;YACZ,OAAO,aAAM,QAAQ,SAAM,CAAA;QAC/B,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,IAAM,KAAK,GAAG,CAAA,MAAA,OAAO,CAAC,KAAK,0CAAE,KAAK,KAAI,CAAC,CAAA;YACvC,OAAO,YAAK,KAAK,cAAI,QAAQ,gBAAM,KAAK,MAAG,CAAA;QAC/C,CAAC;QACD,KAAK,YAAY;YACb,OAAO,cAAO,QAAQ,UAAO,CAAA;QACjC,KAAK,aAAa;YACd,OAAO,cAAO,QAAQ,UAAO,CAAA;QACjC,KAAK,UAAU;YACX,OAAO,cAAO,QAAQ,UAAO,CAAA;QACjC,KAAK,WAAW;YACZ,OAAO,MAAM,CAAA;QACjB;YACI,OAAO,QAAQ,CAAA;IACvB,CAAC;AACL,CAAC;AAED,SAAgB,YAAY,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AACrD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC5B,IAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IACzC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAA;IACtB,OAAO,GAAG,CAAC,SAAS,CAAA;AACxB,CAAC;AAED,SAAgB,WAAW,CAAC,IAAqB;IAC7C,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,OAAO,mBAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE;YACxC,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,QAAQ,EAAE,CAAC,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,CAAC;SACjE,CAAC,CAAA;IACN,CAAC;IAED,uCAAuC;IACvC,OAAO,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import DOMPurify from 'dompurify'\n\nimport {\n ProductTourAppearance,\n ProductTourSelectorError,\n ProductTourStep,\n DEFAULT_PRODUCT_TOUR_APPEARANCE,\n} from '../../posthog-product-tours-types'\nimport { prepareStylesheet } from '../utils/stylesheet-loader'\nimport { document as _document, window as _window } from '../../utils/globals'\nimport { getFontFamily, getContrastingTextColor, hexToRgba } from '../surveys/surveys-extension-utils'\n\nimport productTourStyles from './product-tour.css'\n\nconst document = _document as Document\nconst window = _window as Window & typeof globalThis\n\nexport function getProductTourStylesheet(): HTMLStyleElement | null {\n const stylesheet = prepareStylesheet(document, typeof productTourStyles === 'string' ? productTourStyles : '')\n stylesheet?.setAttribute('data-ph-product-tour-style', 'true')\n return stylesheet\n}\n\nexport interface ElementFindResult {\n element: HTMLElement | null\n error: ProductTourSelectorError | null\n matchCount: number\n}\n\nexport function findElementBySelector(selector: string): ElementFindResult {\n try {\n const elements = document.querySelectorAll(selector)\n\n if (elements.length === 0) {\n return { element: null, error: 'not_found', matchCount: 0 }\n }\n\n const element = elements[0] as HTMLElement\n\n if (!isElementVisible(element)) {\n return { element: null, error: 'not_visible', matchCount: elements.length }\n }\n\n if (elements.length > 1) {\n return { element, error: 'multiple_matches', matchCount: elements.length }\n }\n\n return { element, error: null, matchCount: 1 }\n } catch {\n return { element: null, error: 'not_found', matchCount: 0 }\n }\n}\n\nexport function isElementVisible(element: HTMLElement): boolean {\n const style = window.getComputedStyle(element)\n\n if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {\n return false\n }\n\n const rect = element.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) {\n return false\n }\n\n return true\n}\n\nexport function getElementMetadata(element: HTMLElement): {\n tag: string\n id: string | undefined\n classes: string | undefined\n text: string | undefined\n} {\n return {\n tag: element.tagName,\n id: element.id || undefined,\n classes: element.className || undefined,\n text: element.innerText?.slice(0, 100) || undefined,\n }\n}\n\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right'\n\nexport interface PositionResult {\n top: number\n left: number\n position: TooltipPosition\n}\n\nconst TOOLTIP_MARGIN = 12\nconst TOOLTIP_WIDTH = 320\nconst TOOLTIP_HEIGHT_ESTIMATE = 180\n\nexport function calculateTooltipPosition(targetRect: DOMRect): PositionResult {\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n const spaceBelow = viewportHeight - targetRect.bottom\n const spaceLeft = targetRect.left\n const spaceRight = viewportWidth - targetRect.right\n\n let position: TooltipPosition\n let top: number\n let left: number\n\n if (spaceRight >= TOOLTIP_WIDTH + TOOLTIP_MARGIN) {\n position = 'right'\n top = targetRect.top + targetRect.height / 2 - TOOLTIP_HEIGHT_ESTIMATE / 2\n left = targetRect.right + TOOLTIP_MARGIN\n } else if (spaceLeft >= TOOLTIP_WIDTH + TOOLTIP_MARGIN) {\n position = 'left'\n top = targetRect.top + targetRect.height / 2 - TOOLTIP_HEIGHT_ESTIMATE / 2\n left = targetRect.left - TOOLTIP_WIDTH - TOOLTIP_MARGIN\n } else if (spaceBelow >= TOOLTIP_HEIGHT_ESTIMATE + TOOLTIP_MARGIN) {\n position = 'bottom'\n top = targetRect.bottom + TOOLTIP_MARGIN\n left = targetRect.left + targetRect.width / 2 - TOOLTIP_WIDTH / 2\n } else {\n position = 'top'\n top = targetRect.top - TOOLTIP_HEIGHT_ESTIMATE - TOOLTIP_MARGIN\n left = targetRect.left + targetRect.width / 2 - TOOLTIP_WIDTH / 2\n }\n\n return { top, left, position }\n}\n\nexport function getSpotlightStyle(targetRect: DOMRect, padding: number = 8): Record<string, string> {\n return {\n top: `${targetRect.top - padding}px`,\n left: `${targetRect.left - padding}px`,\n width: `${targetRect.width + padding * 2}px`,\n height: `${targetRect.height + padding * 2}px`,\n }\n}\n\nexport function addProductTourCSSVariablesToElement(element: HTMLElement, appearance?: ProductTourAppearance): void {\n const merged = { ...DEFAULT_PRODUCT_TOUR_APPEARANCE, ...appearance }\n const style = element.style\n\n // User-customizable variables\n style.setProperty('--ph-tour-background-color', merged.backgroundColor)\n style.setProperty('--ph-tour-text-color', merged.textColor)\n style.setProperty('--ph-tour-button-color', merged.buttonColor)\n style.setProperty('--ph-tour-border-radius', `${merged.borderRadius}px`)\n style.setProperty('--ph-tour-button-border-radius', `${merged.buttonBorderRadius}px`)\n style.setProperty('--ph-tour-border-color', merged.borderColor)\n style.setProperty('--ph-tour-font-family', getFontFamily(merged.fontFamily))\n\n // Derived colors\n style.setProperty('--ph-tour-text-secondary-color', hexToRgba(merged.textColor, 0.6))\n style.setProperty('--ph-tour-branding-text-color', getContrastingTextColor(merged.backgroundColor))\n style.setProperty('--ph-tour-button-text-color', getContrastingTextColor(merged.buttonColor))\n style.setProperty('--ph-tour-box-shadow', merged.boxShadow)\n style.setProperty('--ph-tour-overlay-color', merged.showOverlay ? 'rgba(0, 0, 0, 0.5)' : 'transparent')\n\n // Internal styling variables (not customizable)\n style.setProperty('--ph-tour-button-secondary-color', 'transparent')\n style.setProperty('--ph-tour-button-secondary-text-color', merged.textColor)\n style.setProperty('--ph-tour-max-width', '320px')\n style.setProperty('--ph-tour-padding', '16px')\n}\n\nexport function renderTipTapContent(content: any): string {\n if (!content) {\n return ''\n }\n\n if (typeof content === 'string') {\n return escapeHtml(content)\n }\n\n if (content.type === 'text') {\n let text = escapeHtml(content.text || '')\n\n if (content.marks) {\n for (const mark of content.marks) {\n switch (mark.type) {\n case 'bold':\n text = `<strong>${text}</strong>`\n break\n case 'italic':\n text = `<em>${text}</em>`\n break\n case 'underline':\n text = `<u>${text}</u>`\n break\n case 'strike':\n text = `<s>${text}</s>`\n break\n }\n }\n }\n\n return text\n }\n\n const children = content.content?.map(renderTipTapContent).join('') || ''\n\n switch (content.type) {\n case 'doc':\n return children\n case 'paragraph':\n return `<p>${children}</p>`\n case 'heading': {\n const level = content.attrs?.level || 1\n return `<h${level}>${children}</h${level}>`\n }\n case 'bulletList':\n return `<ul>${children}</ul>`\n case 'orderedList':\n return `<ol>${children}</ol>`\n case 'listItem':\n return `<li>${children}</li>`\n case 'hardBreak':\n return '<br>'\n default:\n return children\n }\n}\n\nexport function normalizeUrl(url: string): string {\n return url.endsWith('/') ? url.slice(0, -1) : url\n}\n\nfunction escapeHtml(text: string): string {\n const div = document.createElement('div')\n div.textContent = text\n return div.innerHTML\n}\n\nexport function getStepHtml(step: ProductTourStep): string {\n if (step.contentHtml) {\n return DOMPurify.sanitize(step.contentHtml, {\n ADD_TAGS: ['iframe'],\n ADD_ATTR: ['allowfullscreen', 'frameborder', 'referrerpolicy'],\n })\n }\n\n // backwards compat, will be deprecated\n return renderTipTapContent(step.content)\n}\n"]}
|
|
1
|
+
{"version":3,"file":"product-tours-utils.js","sourceRoot":"","sources":["../../../../src/extensions/product-tours/product-tours-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import DOMPurify from 'dompurify'\n\nimport {\n ProductTourAppearance,\n ProductTourSelectorError,\n ProductTourStep,\n DEFAULT_PRODUCT_TOUR_APPEARANCE,\n} from '../../posthog-product-tours-types'\nimport { prepareStylesheet } from '../utils/stylesheet-loader'\nimport { document as _document, window as _window } from '../../utils/globals'\nimport { getFontFamily, getContrastingTextColor, hexToRgba } from '../surveys/surveys-extension-utils'\n\nimport productTourStyles from './product-tour.css'\n\nconst document = _document as Document\nconst window = _window as Window & typeof globalThis\n\nexport function getProductTourStylesheet(): HTMLStyleElement | null {\n const stylesheet = prepareStylesheet(document, typeof productTourStyles === 'string' ? productTourStyles : '')\n stylesheet?.setAttribute('data-ph-product-tour-style', 'true')\n return stylesheet\n}\n\nexport interface ElementFindResult {\n element: HTMLElement | null\n error: ProductTourSelectorError | null\n matchCount: number\n}\n\nexport function findElementBySelector(selector: string): ElementFindResult {\n try {\n const elements = document.querySelectorAll(selector)\n\n if (elements.length === 0) {\n return { element: null, error: 'not_found', matchCount: 0 }\n }\n\n const element = elements[0] as HTMLElement\n\n if (!isElementVisible(element)) {\n return { element: null, error: 'not_visible', matchCount: elements.length }\n }\n\n if (elements.length > 1) {\n return { element, error: 'multiple_matches', matchCount: elements.length }\n }\n\n return { element, error: null, matchCount: 1 }\n } catch {\n return { element: null, error: 'not_found', matchCount: 0 }\n }\n}\n\nexport function isElementVisible(element: HTMLElement): boolean {\n const style = window.getComputedStyle(element)\n\n if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {\n return false\n }\n\n const rect = element.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) {\n return false\n }\n\n return true\n}\n\nexport function getElementMetadata(element: HTMLElement): {\n tag: string\n id: string | undefined\n classes: string | undefined\n text: string | undefined\n} {\n return {\n tag: element.tagName,\n id: element.id || undefined,\n classes: element.className || undefined,\n text: element.innerText?.slice(0, 100) || undefined,\n }\n}\n\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right'\n\nexport interface PositionResult {\n position: TooltipPosition\n top?: number\n bottom?: number\n left?: number\n right?: number\n}\n\nconst TOOLTIP_MARGIN = 12\n\nexport interface TooltipDimensions {\n width: number\n height: number\n}\n\nexport function calculateTooltipPosition(targetRect: DOMRect, tooltipDimensions: TooltipDimensions): PositionResult {\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n const { width, height } = tooltipDimensions\n const spaceAbove = targetRect.top\n const spaceBelow = viewportHeight - targetRect.bottom\n const spaceLeft = targetRect.left\n const spaceRight = viewportWidth - targetRect.right\n\n const targetCenterY = targetRect.top + targetRect.height / 2\n const targetCenterX = targetRect.left + targetRect.width / 2\n\n if (spaceRight >= width + TOOLTIP_MARGIN) {\n return { position: 'right', top: targetCenterY, left: targetRect.right + TOOLTIP_MARGIN }\n }\n if (spaceLeft >= width + TOOLTIP_MARGIN) {\n return { position: 'left', top: targetCenterY, right: viewportWidth - targetRect.left + TOOLTIP_MARGIN }\n }\n if (spaceAbove >= height + TOOLTIP_MARGIN && spaceBelow < height + TOOLTIP_MARGIN) {\n return { position: 'top', bottom: viewportHeight - targetRect.top + TOOLTIP_MARGIN, left: targetCenterX }\n }\n return { position: 'bottom', top: targetRect.bottom + TOOLTIP_MARGIN, left: targetCenterX }\n}\n\nexport function getSpotlightStyle(targetRect: DOMRect, padding: number = 8): Record<string, string> {\n return {\n top: `${targetRect.top - padding}px`,\n left: `${targetRect.left - padding}px`,\n width: `${targetRect.width + padding * 2}px`,\n height: `${targetRect.height + padding * 2}px`,\n }\n}\n\nexport function addProductTourCSSVariablesToElement(element: HTMLElement, appearance?: ProductTourAppearance): void {\n const merged = { ...DEFAULT_PRODUCT_TOUR_APPEARANCE, ...appearance }\n const style = element.style\n\n // User-customizable variables\n style.setProperty('--ph-tour-background-color', merged.backgroundColor)\n style.setProperty('--ph-tour-text-color', merged.textColor)\n style.setProperty('--ph-tour-button-color', merged.buttonColor)\n style.setProperty('--ph-tour-border-radius', `${merged.borderRadius}px`)\n style.setProperty('--ph-tour-button-border-radius', `${merged.buttonBorderRadius}px`)\n style.setProperty('--ph-tour-border-color', merged.borderColor)\n style.setProperty('--ph-tour-font-family', getFontFamily(merged.fontFamily))\n\n // Derived colors\n style.setProperty('--ph-tour-text-secondary-color', hexToRgba(merged.textColor, 0.6))\n style.setProperty('--ph-tour-branding-text-color', getContrastingTextColor(merged.backgroundColor))\n style.setProperty('--ph-tour-button-text-color', getContrastingTextColor(merged.buttonColor))\n style.setProperty('--ph-tour-box-shadow', merged.boxShadow)\n style.setProperty('--ph-tour-overlay-color', merged.showOverlay ? 'rgba(0, 0, 0, 0.5)' : 'transparent')\n style.setProperty('--ph-tour-z-index', String(merged.zIndex))\n\n // Internal styling variables (not customizable)\n style.setProperty('--ph-tour-button-secondary-color', 'transparent')\n style.setProperty('--ph-tour-button-secondary-text-color', merged.textColor)\n style.setProperty('--ph-tour-max-width', '320px')\n style.setProperty('--ph-tour-padding', '16px')\n}\n\nexport function renderTipTapContent(content: any): string {\n if (!content) {\n return ''\n }\n\n if (typeof content === 'string') {\n return escapeHtml(content)\n }\n\n if (content.type === 'text') {\n let text = escapeHtml(content.text || '')\n\n if (content.marks) {\n for (const mark of content.marks) {\n switch (mark.type) {\n case 'bold':\n text = `<strong>${text}</strong>`\n break\n case 'italic':\n text = `<em>${text}</em>`\n break\n case 'underline':\n text = `<u>${text}</u>`\n break\n case 'strike':\n text = `<s>${text}</s>`\n break\n }\n }\n }\n\n return text\n }\n\n const children = content.content?.map(renderTipTapContent).join('') || ''\n\n switch (content.type) {\n case 'doc':\n return children\n case 'paragraph':\n return `<p>${children}</p>`\n case 'heading': {\n const level = content.attrs?.level || 1\n return `<h${level}>${children}</h${level}>`\n }\n case 'bulletList':\n return `<ul>${children}</ul>`\n case 'orderedList':\n return `<ol>${children}</ol>`\n case 'listItem':\n return `<li>${children}</li>`\n case 'hardBreak':\n return '<br>'\n default:\n return children\n }\n}\n\nexport function normalizeUrl(url: string): string {\n return url.endsWith('/') ? url.slice(0, -1) : url\n}\n\nfunction escapeHtml(text: string): string {\n const div = document.createElement('div')\n div.textContent = text\n return div.innerHTML\n}\n\nexport function getStepHtml(step: ProductTourStep): string {\n if (step.contentHtml) {\n return DOMPurify.sanitize(step.contentHtml, {\n ADD_TAGS: ['iframe'],\n ADD_ATTR: ['allowfullscreen', 'frameborder', 'referrerpolicy'],\n })\n }\n\n // backwards compat, will be deprecated\n return renderTipTapContent(step.content)\n}\n"]}
|
|
@@ -101,6 +101,7 @@ export interface ProductTourAppearance {
|
|
|
101
101
|
whiteLabel?: boolean;
|
|
102
102
|
/** defaults to true, auto-set to false for announcements/banners */
|
|
103
103
|
dismissOnClickOutside?: boolean;
|
|
104
|
+
zIndex?: number;
|
|
104
105
|
}
|
|
105
106
|
export interface ProductTour {
|
|
106
107
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-product-tours-types.js","sourceRoot":"","sources":["../../src/posthog-product-tours-types.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"posthog-product-tours-types.js","sourceRoot":"","sources":["../../src/posthog-product-tours-types.ts"],"names":[],"mappings":";;;AA8Ia,QAAA,+BAA+B,GAAoC;IAC5E,eAAe,EAAE,SAAS;IAC1B,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,SAAS;IACtB,YAAY,EAAE,CAAC;IACf,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,SAAS;IACtB,UAAU,EAAE,WAAW;IACvB,SAAS,EAAE,gCAAgC;IAC3C,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,KAAK;IACjB,qBAAqB,EAAE,IAAI;IAC3B,MAAM,EAAE,UAAU;CACrB,CAAA","sourcesContent":["import { PropertyMatchType } from './types'\nimport { SurveyActionType, SurveyEventWithFilters } from './posthog-surveys-types'\nimport type { InferredSelector } from './extensions/product-tours/element-inference'\nimport { SurveyPosition } from '@posthog/core'\n\nexport interface JSONContent {\n type?: string\n attrs?: Record<string, any>\n content?: JSONContent[]\n marks?: { type: string; attrs?: Record<string, any> }[]\n text?: string\n}\n\nexport type ProductTourStepType = 'element' | 'modal' | 'survey' | 'banner'\n\nexport interface ProductTourBannerConfig {\n behavior: 'sticky' | 'static'\n action?: {\n type: 'none' | 'link' | 'trigger_tour'\n link?: string\n tourId?: string\n }\n}\n\n/** Button actions available on modal steps */\nexport type ProductTourButtonAction = 'dismiss' | 'link' | 'next_step' | 'previous_step' | 'trigger_tour'\n\nexport interface ProductTourStepButton {\n text: string\n action: ProductTourButtonAction\n /** URL to open when action is 'link' */\n link?: string\n /** Tour ID to trigger when action is 'trigger_tour' */\n tourId?: string\n}\n\nexport interface ProductTourStepButtons {\n primary?: ProductTourStepButton\n secondary?: ProductTourStepButton\n}\n\nexport type ProductTourSurveyQuestionType = 'open' | 'rating'\n\nexport interface ProductTourSurveyQuestion {\n type: ProductTourSurveyQuestionType\n questionText: string\n /** Rating display type - emoji or number */\n display?: 'emoji' | 'number'\n /** Rating scale - 3 or 5 for emoji, 5 or 10 for number */\n scale?: 3 | 5 | 10\n /** Label for low end of rating scale (e.g., \"Not likely\") */\n lowerBoundLabel?: string\n /** Label for high end of rating scale (e.g., \"Very likely\") */\n upperBoundLabel?: string\n}\n\nexport interface ProductTourStep {\n id: string\n type: ProductTourStepType\n selector?: string\n progressionTrigger: 'button' | 'click'\n content: JSONContent | null\n /** Pre-rendered HTML content from the editor. If present, SDK should use this instead of rendering from JSONContent. */\n contentHtml?: string\n /** Inline survey question config - if present, this is a survey step */\n survey?: ProductTourSurveyQuestion\n /** ID of the auto-created survey for this step (set by backend) */\n linkedSurveyId?: string\n /** ID of the survey question (set by backend, used for event tracking) */\n linkedSurveyQuestionId?: string\n /** Enhanced element data for more reliable lookup at runtime */\n inferenceData?: InferredSelector\n /** Maximum tooltip width in pixels (defaults to 320px) */\n maxWidth?: number\n /** Position for modal/survey steps (defaults to middle_center) */\n modalPosition?: SurveyPosition\n /** Button configuration for modal steps */\n buttons?: ProductTourStepButtons\n /** Banner configuration (only for banner steps) */\n bannerConfig?: ProductTourBannerConfig\n}\n\nexport interface ProductTourConditions {\n url?: string\n urlMatchType?: PropertyMatchType\n selector?: string\n autoShowDelaySeconds?: number\n events?: {\n values: SurveyEventWithFilters[]\n } | null\n cancelEvents?: {\n values: SurveyEventWithFilters[]\n } | null\n actions?: {\n values: SurveyActionType[]\n } | null\n}\n\nexport interface ProductTourAppearance {\n backgroundColor?: string\n textColor?: string\n buttonColor?: string\n borderRadius?: number\n buttonBorderRadius?: number\n borderColor?: string\n fontFamily?: string\n boxShadow?: string\n showOverlay?: boolean\n whiteLabel?: boolean\n /** defaults to true, auto-set to false for announcements/banners */\n dismissOnClickOutside?: boolean\n zIndex?: number\n}\n\nexport interface ProductTour {\n id: string\n name: string\n description?: string\n type: 'product_tour'\n auto_launch?: boolean\n start_date: string | null\n end_date: string | null\n current_iteration?: number\n conditions?: ProductTourConditions\n appearance?: ProductTourAppearance\n steps: ProductTourStep[]\n internal_targeting_flag_key?: string\n linked_flag_key?: string\n}\n\nexport type ProductTourCallback = (tours: ProductTour[], context?: { isLoaded: boolean; error?: string }) => void\n\nexport type ProductTourSelectorError = 'not_found' | 'multiple_matches' | 'not_visible'\n\nexport type ProductTourDismissReason =\n | 'user_clicked_skip'\n | 'user_clicked_outside'\n | 'escape_key'\n | 'element_unavailable'\n\nexport type ProductTourRenderReason = 'auto' | 'api' | 'trigger' | 'event'\n\nexport const DEFAULT_PRODUCT_TOUR_APPEARANCE: Required<ProductTourAppearance> = {\n backgroundColor: '#ffffff',\n textColor: '#1d1f27',\n buttonColor: '#1d1f27',\n borderRadius: 8,\n buttonBorderRadius: 6,\n borderColor: '#e5e7eb',\n fontFamily: 'system-ui',\n boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',\n showOverlay: true,\n whiteLabel: false,\n dismissOnClickOutside: true,\n zIndex: 2147483646,\n}\n\nexport interface ShowTourOptions {\n reason?: ProductTourRenderReason\n enableStrictValidation?: boolean\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "posthog-js",
|
|
3
|
-
"version": "1.321.
|
|
3
|
+
"version": "1.321.3",
|
|
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",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@opentelemetry/resources": "^2.2.0",
|
|
29
29
|
"@opentelemetry/sdk-logs": "^0.208.0",
|
|
30
30
|
"@posthog/core": "1.9.1",
|
|
31
|
-
"@posthog/types": "1.321.
|
|
31
|
+
"@posthog/types": "1.321.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@babel/core": "^7.27.1",
|