UNPKG

react-native-acoustic-connect-beta

Version:

BETA: React native plugin for Acoustic Connect

282 lines (257 loc) 13.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createTrackedDialogComponents = createTrackedDialogComponents; exports.useTrackedDialogs = useTrackedDialogs; exports.withAcousticAutoDialog = withAcousticAutoDialog; var _react = _interopRequireWildcard(require("react")); var _useDialogTracking = require("./useDialogTracking"); var _index = _interopRequireDefault(require("../index")); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /******************************************************************************************** * Copyright (C) 2025 Acoustic, L.P. All rights reserved. * * NOTICE: This file contains material that is confidential and proprietary to * Acoustic, L.P. and/or other developers. No license is granted under any intellectual or * industrial property rights of Acoustic, L.P. except as may be provided in an agreement with * Acoustic, L.P. Any unauthorized copying or distribution of content from this file is * prohibited. * * Created by Omar Hernandez on 5/9/25. * ********************************************************************************************/ /** * HOC Wrapper that automatically tracks dialog show/dismiss events and button clicks * Works with any dialog component that has 'visible' and 'onDismiss' props * * Supported Dialog Patterns: * - react-native-paper Dialog components * - Custom modal components with visible/onDismiss props * - Components with different prop names (show/hide, open/close, etc.) * - Components with custom button implementations * - Components with nested dialog structures */ function withAcousticAutoDialog(DialogComponent) { return /*#__PURE__*/(0, _react.forwardRef)((props, ref) => { const { generateDialogId } = (0, _useDialogTracking.useDialogTracking)(); const dialogIdRef = (0, _react.useRef)(null); const isVisibleRef = (0, _react.useRef)(false); // Track button click event const trackButtonClick = (0, _react.useCallback)((buttonText, buttonIndex) => { if (dialogIdRef.current) { _index.default.logDialogButtonClickEvent(dialogIdRef.current, buttonText, buttonIndex); console.log(`🔍 withAcousticAutoDialog: Button clicked - ${buttonText} (${dialogIdRef.current})`); } }, []); // Wrap button onPress handlers to track clicks const wrapButtonOnPress = (0, _react.useCallback)((originalOnPress, buttonText, buttonIndex) => { return () => { trackButtonClick(buttonText, buttonIndex); if (originalOnPress) { originalOnPress(); } }; }, [trackButtonClick]); // Recursively wrap buttons in children const wrapButtonsInChildren = (0, _react.useCallback)((children, buttonIndex = 0) => { if (!children) return children; if (Array.isArray(children)) { return children.map((child, index) => wrapButtonsInChildren(child, buttonIndex + index)); } if (/*#__PURE__*/_react.default.isValidElement(children)) { const childProps = children.props; // Check if this is a button component (supports various button types) const isButton = typeof children.type === 'function' && (children.type.displayName === 'Button' || children.type.name === 'Button' || children.type.displayName === 'DialogAction' || children.type.name === 'DialogAction' || children.type.displayName === 'TouchableOpacity' || children.type.name === 'TouchableOpacity' || children.type.displayName === 'Pressable' || children.type.name === 'Pressable') || childProps && (childProps.onPress || childProps.onPressIn || childProps.onPressOut || childProps.onTouchEnd); if (isButton && childProps?.onPress) { const buttonText = childProps.children || childProps.title || 'Button'; return /*#__PURE__*/_react.default.cloneElement(children, { ...childProps, onPress: wrapButtonOnPress(childProps.onPress, buttonText, buttonIndex) }); } // Recursively wrap buttons in nested children if (childProps?.children) { return /*#__PURE__*/_react.default.cloneElement(children, { ...childProps, children: wrapButtonsInChildren(childProps.children, buttonIndex) }); } } return children; }, [wrapButtonOnPress]); // Track dialog show event when visible changes to true // Supports various visibility prop names: visible, show, open, isOpen, isVisible const isVisible = props.visible || props.show || props.open || props.isOpen || props.isVisible; (0, _react.useEffect)(() => { if (isVisible && !isVisibleRef.current) { const dialogId = generateDialogId(); dialogIdRef.current = dialogId; isVisibleRef.current = true; // Get dialog title from various possible sources const getDialogTitle = () => { // Try to get title from props (supports various prop names) if (props.title) return props.title; if (props.dialogTitle) return props.dialogTitle; if (props.header) return props.header; if (props.heading) return props.heading; if (props.name) return props.name; // Try to get title from children (for react-native-paper Dialog) if (props.children) { console.log(`🔍 withAcousticAutoDialog: Starting title extraction from children`); console.log(`🔍 withAcousticAutoDialog: Initial children:`, props.children); const extractTitleFromChildren = (children, depth = 0) => { if (!children) return null; if (Array.isArray(children)) { for (const child of children) { const title = extractTitleFromChildren(child, depth + 1); if (title) return title; } return null; } if (/*#__PURE__*/_react.default.isValidElement(children)) { const childProps = children.props; // Debug: Log component info for debugging console.log(`🔍 withAcousticAutoDialog: Processing component at depth ${depth}:`, { type: children.type, displayName: children.type?.displayName, name: children.type?.name, hasChildren: !!childProps?.children, childrenType: typeof childProps?.children }); // Check if this is a Dialog component from react-native-paper if (children.type && typeof children.type === 'function' && (children.type.displayName === 'Dialog' || children.type.name === 'Dialog')) { console.log(`🔍 withAcousticAutoDialog: Found Dialog component at depth ${depth}`); // Extract title from Dialog children if (childProps?.children) { return extractTitleFromChildren(childProps.children, depth + 1); } } // Check if this is a Portal component (common wrapper for dialogs) if (children.type && typeof children.type === 'function' && (children.type.displayName === 'Portal' || children.type.name === 'Portal')) { console.log(`🔍 withAcousticAutoDialog: Found Portal component at depth ${depth}`); // Extract title from Portal children if (childProps?.children) { return extractTitleFromChildren(childProps.children, depth + 1); } } // Check if this is a DialogTitle component (supports various title component types) if (children.type && typeof children.type === 'function' && (children.type.displayName === 'DialogTitle' || children.type.name === 'DialogTitle' || children.type.displayName === 'Title' || children.type.name === 'Title' || children.type.displayName === 'Header' || children.type.name === 'Header' || children.type.displayName === 'Heading' || children.type.name === 'Heading')) { if (childProps?.children && typeof childProps.children === 'string') { console.log(`🔍 withAcousticAutoDialog: Found title in title component: "${childProps.children}"`); return childProps.children; } } // Check if this component has title content if (childProps?.title) { return childProps.title; } // Recursively search in nested children if (childProps?.children) { return extractTitleFromChildren(childProps.children, depth + 1); } } return null; }; const title = extractTitleFromChildren(props.children); if (title) { console.log(`🔍 withAcousticAutoDialog: Found title from children: "${title}"`); return title; } } return 'Dialog'; }; const title = getDialogTitle(); // Log dialog show event _index.default.logDialogShowEvent(dialogId, title, 'custom'); console.log(`🔍 withAcousticAutoDialog: Dialog shown - ${title} (${dialogId})`); } else if (!isVisible && isVisibleRef.current) { // Track dialog dismiss event when visible changes to false if (dialogIdRef.current) { _index.default.logDialogDismissEvent(dialogIdRef.current, 'user_action'); console.log(`🔍 withAcousticAutoDialog: Dialog dismissed - ${dialogIdRef.current}`); dialogIdRef.current = null; } isVisibleRef.current = false; } }, [isVisible, generateDialogId]); // Handle dismiss events (supports various dismiss prop names) const handleDismiss = () => { if (dialogIdRef.current) { _index.default.logDialogDismissEvent(dialogIdRef.current, 'user_action'); console.log(`🔍 withAcousticAutoDialog: Dialog dismissed via dismiss handler - ${dialogIdRef.current}`); dialogIdRef.current = null; } isVisibleRef.current = false; // Call original dismiss handler if it exists (supports various prop names) if (props.onDismiss) { props.onDismiss(); } else if (props.onClose) { props.onClose(); } else if (props.onHide) { props.onHide(); } else if (props.close) { props.close(); } else if (props.hide) { props.hide(); } }; // Forward ref to the wrapped component (0, _react.useImperativeHandle)(ref, () => { return { ...ref // Add any additional methods if needed }; }, [ref]); // Wrap buttons in children to track clicks const wrappedChildren = wrapButtonsInChildren(props.children); // Determine which dismiss prop to use based on what the original component expects const dismissProps = {}; if (props.onDismiss) { dismissProps.onDismiss = handleDismiss; } else if (props.onClose) { dismissProps.onClose = handleDismiss; } else if (props.onHide) { dismissProps.onHide = handleDismiss; } else if (props.close) { dismissProps.close = handleDismiss; } else if (props.hide) { dismissProps.hide = handleDismiss; } else { // Default to onDismiss if no dismiss prop is found dismissProps.onDismiss = handleDismiss; } return /*#__PURE__*/(0, _jsxRuntime.jsx)(DialogComponent, { ...props, ...dismissProps, ref: ref, children: wrappedChildren }); }); } /** * Convenience function to create tracked versions of common dialog components */ function createTrackedDialogComponents() { // Note: These would need to be imported in the consuming app // This is just a template for how to use the HOC return { // Example usage (uncomment when react-native-paper is available): // TrackedDialog: withAcousticAutoDialog(require('react-native-paper').Dialog), // TrackedPortal: withAcousticAutoDialog(require('react-native-paper').Portal), }; } /** * Hook to get tracked dialog components */ function useTrackedDialogs() { return { withAcousticAutoDialog, createTrackedDialogComponents }; } //# sourceMappingURL=withAcousticAutoDialog.js.map