UNPKG

react-facebook

Version:

Facebook components like a Login button, Like, Share, Comments, Embedded Post/Video, Messenger Chat, and Facebook Pixel tracking

1,202 lines (1,163 loc) 40 kB
'use strict'; var React = require('react'); var LoginStatus; (function (LoginStatus) { LoginStatus["CONNECTED"] = "connected"; LoginStatus["AUTHORIZATION_EXPIRED"] = "authorization_expired"; LoginStatus["NOT_AUTHORIZED"] = "not_authorized"; LoginStatus["UNKNOWN"] = "unknown"; })(LoginStatus || (LoginStatus = {})); var LoginStatus$1 = LoginStatus; class FBError extends Error { constructor(message, code, type) { super(message); this.code = code; this.type = type; } } var Method; (function (Method) { Method["GET"] = "get"; Method["POST"] = "post"; Method["DELETE"] = "delete"; })(Method || (Method = {})); var Namespace; (function (Namespace) { Namespace["UI"] = "ui"; Namespace["API"] = "api"; Namespace["LOGIN"] = "login"; Namespace["LOGOUT"] = "logout"; Namespace["GET_LOGIN_STATUS"] = "getLoginStatus"; Namespace["GET_AUTH_RESPONSE"] = "getAuthResponse"; })(Namespace || (Namespace = {})); const defaultOptions = { domain: 'connect.facebook.net', version: 'v23.0', cookie: false, status: false, xfbml: false, language: 'en_US', frictionlessRequests: false, debug: false, chatSupport: false, autoLogAppEvents: true, lazy: false, }; class Facebook { constructor(options) { if (!options.appId) { throw new Error('You need to set appId'); } this.options = { ...defaultOptions, ...options, }; if (!this.options.lazy) { this.init(); } } getAppId() { return this.options.appId; } getFB() { return window.FB; } async init() { if (this.loadingPromise) { return this.loadingPromise; } this.loadingPromise = new Promise((resolve) => { const { domain, language, debug, chatSupport, ...restOptions } = this.options; window.fbAsyncInit = () => { window.FB.init({ appId: restOptions.appId, version: restOptions.version, cookie: restOptions.cookie, status: restOptions.status, xfbml: restOptions.xfbml, frictionlessRequests: restOptions.frictionlessRequests, }); resolve(this); }; if (window.document.getElementById('facebook-jssdk')) { return resolve(this); } const js = window.document.createElement('script'); js.id = 'facebook-jssdk'; js.async = true; js.defer = true; js.crossOrigin = 'anonymous'; js.src = `https://${domain}/${language}/sdk${chatSupport ? '/xfbml.customerchat' : ''}${debug ? '/debug' : ''}.js`; window.document.body.appendChild(js); }); return this.loadingPromise; } async process(namespace, before = [], after = []) { await this.init(); const fb = this.getFB(); return new Promise((resolve, reject) => { const callback = (response) => { if (!response) { if (namespace === Namespace.UI) return; reject(new Error('Response is undefined')); } else if (!!response && typeof response === 'object' && 'error' in response) { const { code, type, message } = response.error; reject(new FBError(message, code, type)); } else { resolve(response); } }; fb[namespace](...before, callback, ...after); }); } async ui(options) { return this.process(Namespace.UI, [options]); } async api(path, method = Method.GET, params = {}) { return this.process(Namespace.API, [path, method, params]); } async login(options) { const { scope, authType = [], returnScopes, rerequest, reauthorize } = options; const loginOptions = { scope, }; if (returnScopes) { loginOptions.return_scopes = true; } if (rerequest) { authType.push('rerequest'); } if (reauthorize) { authType.push('reauthenticate'); } if (authType.length) { loginOptions.auth_type = authType.join(','); } return this.process(Namespace.LOGIN, [], [loginOptions]); } async logout() { return this.process(Namespace.LOGOUT); } async getLoginStatus() { return this.process(Namespace.GET_LOGIN_STATUS); } async getAuthResponse() { return this.process(Namespace.GET_AUTH_RESPONSE); } async getTokenDetail(loginResponse) { if ((loginResponse === null || loginResponse === void 0 ? void 0 : loginResponse.status) === LoginStatus$1.CONNECTED) { return loginResponse.authResponse; } const response = await this.getLoginStatus(); if (response.status === LoginStatus$1.CONNECTED) { return response.authResponse; } throw new Error('Token is undefined'); } async getProfile(params) { return this.api('/me', Method.GET, params); } async getTokenDetailWithProfile(params, response) { const tokenDetail = await this.getTokenDetail(response); const profile = await this.getProfile(params); return { profile, tokenDetail, }; } async getToken() { const authResponse = await this.getTokenDetail(); return authResponse.accessToken; } async getUserId() { const authResponse = await this.getTokenDetail(); return authResponse.userID; } async sendInvite(to, options) { return this.ui({ to, method: 'apprequests', ...options, }); } async postAction(ogNamespace, ogAction, ogObject, ogObjectUrl, noFeedStory = false) { let url = `/me/${ogNamespace}:${ogAction}?${ogObject}=${encodeURIComponent(ogObjectUrl)}`; if (noFeedStory === true) { url += '&no_feed_story=true'; } return this.api(url, Method.POST); } async getPermissions() { const response = await this.api('/me/permissions'); return response.data; } async hasPermissions(permissions) { const usersPermissions = await this.getPermissions(); const findedPermissions = permissions.filter((p) => { const currentPermission = usersPermissions.find((row) => { const { permission, status } = row; return status === 'granted' && permission === p; }); return !!currentPermission; }); return findedPermissions.length === permissions.length; } async subscribe(eventName, callback) { await this.init(); this.getFB().Event.subscribe(eventName, callback); return () => this.unsubscribe(eventName, callback); } async unsubscribe(eventName, callback) { await this.init(); this.getFB().Event.unsubscribe(eventName, callback); } async parse(parentNode) { await this.init(); if (typeof parentNode === 'undefined') { this.getFB().XFBML.parse(); } else { this.getFB().XFBML.parse(parentNode); } } async getRequests() { return this.api('/me/apprequests'); } async removeRequest(requestId) { return this.api(requestId, Method.DELETE); } async setAutoGrow() { await this.init(); this.getFB().Canvas.setAutoGrow(); } async paySimple(product, quantity = 1) { return this.ui({ method: 'pay', action: 'purchaseitem', product, quantity, }); } async pay(product, options) { return this.ui({ method: 'pay', action: 'purchaseitem', product, ...options, }); } getLocale() { return this.options.language || 'en_US'; } async changeLocale(newLocale) { // Update the options this.options.language = newLocale; // Remove existing Facebook SDK script const existingScript = window.document.getElementById('facebook-jssdk'); if (existingScript) { existingScript.remove(); } // Clear existing FB object if (window.FB) { delete window.FB; } // Reset loading promise to force re-initialization this.loadingPromise = undefined; // Re-initialize with new locale await this.init(); // Re-parse all existing Facebook widgets on the page await this.parseAll(); } async parseAll() { await this.init(); const fb = this.getFB(); if (fb && fb.XFBML && fb.XFBML.parse) { // Parse all Facebook widgets on the page fb.XFBML.parse(); } } } var FacebookContext = React.createContext(undefined); const defaultPixelOptions = { autoConfig: true, debug: false, advancedMatching: {}, }; class FacebookPixel { constructor(options) { if (!options.pixelId) { throw new Error('You need to set pixelId'); } this.options = { ...defaultPixelOptions, ...options, }; if (!this.options.debug) { this.options.debug = false; } } warn(...args) { if (!this.options.debug) return; console.warn('[react-facebook-pixel]', ...args); } log(...args) { if (!this.options.debug) return; console.info('[react-facebook-pixel]', ...args); } loadPixelScript() { return new Promise((resolve) => { // Check if already loaded if (window.fbq) { resolve(); return; } // Load Facebook Pixel script const script = document.createElement('script'); script.async = true; script.src = 'https://connect.facebook.net/en_US/fbevents.js'; script.onload = () => { // Initialize fbq function if (!window.fbq) { window.fbq = function () { window.fbq.callMethod ? window.fbq.callMethod.apply(window.fbq, arguments) : window.fbq.queue.push(arguments); }; } if (!window._fbq) { window._fbq = window.fbq; } window.fbq.push = window.fbq; window.fbq.loaded = true; window.fbq.version = '2.0'; window.fbq.queue = []; resolve(); }; script.onerror = () => { this.warn('Failed to load Facebook Pixel script'); resolve(); }; document.head.appendChild(script); }); } async init() { if (this.loadingPromise) { return this.loadingPromise; } this.loadingPromise = this.loadPixelScript().then(() => { const { pixelId, autoConfig, advancedMatching } = this.options; if (autoConfig === false) { window.fbq('set', 'autoConfig', false, pixelId); } window.fbq('init', pixelId, advancedMatching); this.log('Pixel initialized successfully'); return this; }); return this.loadingPromise; } async pageView() { await this.init(); window.fbq('track', 'PageView'); this.log("Called fbq('track', 'PageView')"); } async track(eventName, data) { await this.init(); window.fbq('track', eventName, data); this.log(`Called fbq('track', '${eventName}')`); if (data) { this.log('with data:', data); } } async trackSingle(pixelId, eventName, data) { await this.init(); window.fbq('trackSingle', pixelId, eventName, data); this.log(`Called fbq('trackSingle', '${pixelId}', '${eventName}')`); if (data) { this.log('with data:', data); } } async trackCustom(eventName, data) { await this.init(); window.fbq('trackCustom', eventName, data); this.log(`Called fbq('trackCustom', '${eventName}')`); if (data) { this.log('with data:', data); } } async trackSingleCustom(pixelId, eventName, data) { await this.init(); window.fbq('trackSingleCustom', pixelId, eventName, data); this.log(`Called fbq('trackSingleCustom', '${pixelId}', '${eventName}')`); if (data) { this.log('with data:', data); } } async grantConsent() { await this.init(); window.fbq('consent', 'grant'); this.log("Called fbq('consent', 'grant')"); } async revokeConsent() { await this.init(); window.fbq('consent', 'revoke'); this.log("Called fbq('consent', 'revoke')"); } // Direct access to fbq for advanced use cases async fbq(...args) { await this.init(); window.fbq(...args); this.log(`Called fbq('${args.slice(0, 2).join("', '")}')`); if (args[2]) { this.log('with data:', args[2]); } } isInitialized() { return !!this.loadingPromise; } getOptions() { return { ...this.options }; } } const FacebookPixelContext = React.createContext(undefined); function FacebookPixelProvider(props) { const { children, lazy = false, ...options } = props; const [isLoading, setIsLoading] = React.useState(true); const [error, setError] = React.useState(); const pixelRef = React.useRef(); const initPromiseRef = React.useRef(); async function init() { if (initPromiseRef.current) { return initPromiseRef.current; } initPromiseRef.current = (async () => { try { if (pixelRef.current) { return; } setIsLoading(true); setError(undefined); pixelRef.current = new FacebookPixel(options); await pixelRef.current.init(); } catch (error) { setError(error); } finally { setIsLoading(false); } })(); return initPromiseRef.current; } async function pageView() { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.pageView()); } async function track(eventName, data) { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.track(eventName, data)); } async function trackCustom(eventName, data) { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.trackCustom(eventName, data)); } async function grantConsent() { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.grantConsent()); } async function revokeConsent() { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.revokeConsent()); } async function fbq(...args) { var _a; await init(); await ((_a = pixelRef.current) === null || _a === void 0 ? void 0 : _a.fbq(...args)); } React.useEffect(() => { if (!lazy) { init(); } }, [lazy]); const value = { isLoading, error, init, pixel: pixelRef.current, pageView, track, trackCustom, grantConsent, revokeConsent, fbq, }; return (React.createElement(FacebookPixelContext.Provider, { value: value }, children)); } function FacebookProvider(props) { const { children, pixel, ...options } = props; const [isLoading, setIsLoading] = React.useState(true); const [isReady, setIsReady] = React.useState(false); const [error, setError] = React.useState(); const [locale, setLocaleState] = React.useState(options.language || 'en_US'); const apiRef = React.useRef(); const initPromiseRef = React.useRef(); async function init() { if (initPromiseRef.current) { return initPromiseRef.current; } initPromiseRef.current = (async () => { try { if (apiRef.current) { return apiRef.current; } setIsReady(false); setIsLoading(true); apiRef.current = new Facebook(options); await apiRef.current.init(); setIsReady(true); return apiRef.current; } catch (error) { setError(error); } finally { setIsLoading(false); } return apiRef.current; })(); return initPromiseRef.current; } async function parse(element) { const api = await init(); if (api) { await api.parse(element); } } async function setLocale(newLocale) { if (!apiRef.current) { // If API not initialized yet, just update the state setLocaleState(newLocale); return; } try { setIsLoading(true); setError(undefined); // Change locale on the Facebook API instance await apiRef.current.changeLocale(newLocale); // Update local state setLocaleState(newLocale); } catch (error) { setError(error); } finally { setIsLoading(false); } } React.useEffect(() => { const { lazy } = options; if (!lazy) { init(); } }, [options.lazy]); React.useEffect(() => { const newLocale = options.language || 'en_US'; if (newLocale !== locale) { setLocale(newLocale); } }, [options.language, locale]); const value = { isLoading, error, init, api: isReady ? apiRef.current : undefined, parse, locale, setLocale, }; const content = (React.createElement(FacebookContext.Provider, { value: value }, children)); // Wrap with pixel provider if pixel config is provided if (pixel) { return (React.createElement(FacebookPixelProvider, { ...pixel }, content)); } return content; } function useFacebook(props = {}) { const { lazy = false } = props; const context = React.useContext(FacebookContext); if (!context) { throw new Error('useFacebook must be used within a FacebookProvider'); } React.useEffect(() => { if (!lazy) { context.init(); } }, [lazy, context.init]); return context; } function Parser(props, forwardedRef) { const { as: As = 'div', children, className, style, data } = props; const { parse } = useFacebook(); const [element, setElement] = React.useState(null); const handleRef = React.useCallback((element) => { setElement(element); if (forwardedRef) { if (typeof forwardedRef === 'function') { forwardedRef(element); } else if (forwardedRef) { forwardedRef.current = element; } } }, [forwardedRef]); const key = React.useMemo(() => { let uniqueKey = `fb-parser-${As}-${className}`; if (!data) { return uniqueKey; } for (const key in data) { const value = data[key]; if (value !== undefined) { uniqueKey += `-${key}:${data[key] || ''}`; } } return uniqueKey; }, [data, children, As, className]); React.useEffect(() => { if (element) { parse(element); } }, [element, parse, key]); return React.createElement(As, { key: key, style: style, ref: handleRef }, React.createElement(As, { className: className, ...data }, children)); } var Parser$1 = React.memo(React.forwardRef(Parser)); const canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement); function getCurrentHref() { if (!canUseDOM) { return 'https://www.facebook.com'; } return window.location.href; } function Like(props, ref) { const { className = '', href = getCurrentHref(), layout, colorScheme, action, showFaces, share, width, size, kidDirectedSite, referral, lazy, ...rest } = props; const data = React.useMemo(() => { return { 'data-ref': referral, 'data-href': href, 'data-layout': layout, 'data-colorscheme': colorScheme, 'data-action': action, 'data-show-faces': showFaces ? 'true' : 'false', 'data-share': share ? 'true' : 'false', 'data-width': width === null || width === void 0 ? void 0 : width.toString(), 'data-size': size, 'data-lazy': lazy ? 'true' : 'false', 'data-kid-directed-site': kidDirectedSite ? 'true' : 'false', }; }, [referral, href, layout, colorScheme, action, showFaces, share, width, size, kidDirectedSite, lazy]); return (React.createElement(Parser$1, { className: `fb-like ${className}`, data: data, ...rest, ref: ref })); } var Like$1 = React.memo(React.forwardRef(Like)); function clearUndefinedProperties(obj) { return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined)); } function useShare() { const { init } = useFacebook(); const [isLoading, setIsLoading] = React.useState(false); const [error, setError] = React.useState(undefined); async function handleShare(options) { try { const { href, display, hashtag, redirectUri, ...rest } = options; setError(undefined); setIsLoading(true); const api = await init(); if (!api) { throw new Error('Facebook API is not initialized'); } return api.ui(clearUndefinedProperties({ method: 'share', href, display, app_id: api.getAppId(), hashtag, redirect_uri: redirectUri, ...rest, })); } catch (error) { setError(error); throw error; } finally { setIsLoading(false); } } return { isLoading, error, share: handleShare, }; } function ShareButton(props) { const { as: AsChild = 'button', disabled, href, display, hashtag, redirectUri, ...rest } = props; const { isLoading, share } = useShare(); function handleShare() { if (isLoading) { return; } share({ href, display, hashtag, redirectUri, }); } return (React.createElement(AsChild, { onClick: handleShare, disabled: isLoading, ...rest })); } function Page(props, ref) { const { className = '', style, href = getCurrentHref(), tabs, hideCover, width, height, showFacepile, hideCTA, smallHeader, adaptContainerWidth, lazy, ...rest } = props; const data = React.useMemo(() => { return { 'data-tabs': tabs, 'data-hide-cover': hideCover ? 'true' : 'false', 'data-show-facepile': showFacepile ? 'true' : 'false', 'data-hide-cta': hideCTA ? 'true' : 'false', 'data-href': href, 'data-small-header': smallHeader ? 'true' : 'false', 'data-adapt-container-width': adaptContainerWidth ? 'true' : 'false', 'data-height': height === null || height === void 0 ? void 0 : height.toString(), 'data-width': width === null || width === void 0 ? void 0 : width.toString(), 'data-lazy': lazy ? 'true' : 'false', }; }, [href, tabs, hideCover, width, height, showFacepile, hideCTA, smallHeader, adaptContainerWidth, lazy]); return (React.createElement(Parser$1, { className: `fb-page ${className}`, style: style, data: data, ...rest, ref: ref })); } var Page$1 = React.memo(React.forwardRef(Page)); function useLogin() { const { api, isLoading } = useFacebook(); const [error, setError] = React.useState(undefined); const [isLoadingLogin, setIsLoadingLogin] = React.useState(false); const [latestResponse, setLatestResponse] = React.useState(); async function handleLogin(loginOptions, callback) { try { if (!api) { throw new Error('Facebook API is not initialized'); } setIsLoadingLogin(true); const response = await api.login(loginOptions); if (response.status !== LoginStatus$1.CONNECTED) { throw new Error('Unauthorized user'); } setLatestResponse(response); callback === null || callback === void 0 ? void 0 : callback(response); return response; } catch (error) { setError(error); throw (error); } finally { setIsLoadingLogin(false); } } return { login: handleLogin, error, isLoading: isLoading || isLoadingLogin, status: latestResponse === null || latestResponse === void 0 ? void 0 : latestResponse.status, }; } function useSubscribe(event, callback) { const [lastValue, setLastValue] = React.useState(undefined); const { init } = useFacebook(); const handleResponse = React.useCallback((value) => { setLastValue(value); callback === null || callback === void 0 ? void 0 : callback(value); }, [callback]); const handleSubscribe = React.useCallback(async () => { const api = await init(); if (api) { await api.subscribe(event, handleResponse); } }, [event, handleResponse, init]); const handleUnsubscribe = React.useCallback(async () => { const api = await init(); if (api) { await api.unsubscribe(event, handleResponse); } }, [event, handleResponse, init]); React.useEffect(() => { handleSubscribe(); return () => { handleUnsubscribe(); }; }, [handleSubscribe, handleUnsubscribe]); return lastValue; } function useLoginStatus() { const { init } = useFacebook(); const [isLoading, setIsLoading] = React.useState(true); const [error, setError] = React.useState(undefined); const [status, setStatus] = React.useState(LoginStatus$1.UNKNOWN); const handleStatusChanges = React.useCallback((response) => { setStatus(response.status); }, []); useSubscribe('auth.statusChange', handleStatusChanges); async function handleGetInitState() { try { setIsLoading(true); const api = await init(); if (!api) { throw new Error('Facebook API is not initialized'); } const { status } = await api.getLoginStatus(); setStatus(status); } catch (error) { setError(error); } finally { setIsLoading(false); } } React.useEffect(() => { handleGetInitState(); }, []); return { isLoading, error, status, }; } function useProfile(fields) { const { init } = useFacebook(); const { status } = useLoginStatus(); const [isLoading, setIsLoading] = React.useState(true); const [profile, setProfile] = React.useState(undefined); const [error, setError] = React.useState(undefined); async function updateProfile() { try { setError(undefined); setIsLoading(true); const api = await init(); if (!api) { throw new Error('Facebook API is not initialized'); } if (status === LoginStatus$1.CONNECTED) { const profile = await api.getProfile({ fields, }); setProfile(profile); } } catch (error) { setError(error); } finally { setIsLoading(false); } } React.useEffect(() => { updateProfile(); }, [status, fields, init]); return { isLoading, error, profile, }; } function Login(props) { const { children, onSuccess, onError, onProfileSuccess, fields = [], as: Component = 'button', disabled = false, scope = ['public_profile', 'email'], returnScopes, authType, rerequest, reauthorize, ...rest } = props; const { isLoading, login } = useLogin(); const { profile } = useProfile(fields); React.useEffect(() => { if (profile && onProfileSuccess) { onProfileSuccess(profile); } }, [profile, onProfileSuccess]); const handleLogin = async () => { if (isLoading || disabled) return; try { const response = await login({ scope: Array.isArray(scope) ? scope.join(',') : scope, returnScopes, authType, rerequest, reauthorize, }); onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(response); } catch (error) { onError === null || onError === void 0 ? void 0 : onError(error); } }; const isDisabled = disabled || isLoading; // Render props pattern if (typeof children === 'function') { return children({ onClick: handleLogin, isLoading, isDisabled, }); } // Default button rendering return (React.createElement(Component, { onClick: handleLogin, disabled: isDisabled, ...rest }, isLoading ? 'Loading...' : (children || 'Login with Facebook'))); } function EmbeddedPost(props, ref) { const { className = '', href, width, showText, lazy, ...rest } = props; const data = React.useMemo(() => { return { 'data-href': href, 'data-width': width === null || width === void 0 ? void 0 : width.toString(), 'data-lazy': lazy ? 'true' : 'false', 'data-show-text': showText ? 'true' : 'false', }; }, [href, width, lazy, showText]); return (React.createElement(Parser$1, { className: `fb-post ${className}`, data: data, ...rest, ref: ref })); } var EmbeddedPost$1 = React.memo(React.forwardRef(EmbeddedPost)); function EmbeddedVideo(props, ref) { const { className = '', href, width, showText, allowFullScreen, autoPlay, lazy, showCaptions, ...rest } = props; const data = React.useMemo(() => { return { 'data-href': href, 'data-width': width === null || width === void 0 ? void 0 : width.toString(), 'data-show-text': showText ? 'true' : 'false', 'data-show-captions': showCaptions ? 'true' : 'false', 'data-autoplay': autoPlay ? 'true' : 'false', 'data-lazy': lazy ? 'true' : 'false', 'data-allowfullscreen': allowFullScreen ? 'true' : 'false', }; }, [href, width, showText, showCaptions, autoPlay, lazy, allowFullScreen]); return (React.createElement(Parser$1, { className: `fb-video ${className}`, data: data, ...rest, ref: ref })); } var EmbeddedVideo$1 = React.memo(React.forwardRef(EmbeddedVideo)); function Comments(props, ref) { const { className = '', colorScheme, href = getCurrentHref(), numPosts, orderBy, width, mobile, lazy, ...rest } = props; const data = React.useMemo(() => { return { 'data-colorscheme': colorScheme, 'data-numposts': numPosts === null || numPosts === void 0 ? void 0 : numPosts.toString(), 'data-href': href, 'data-order-by': orderBy, 'data-width': width === null || width === void 0 ? void 0 : width.toString(), 'data-skin': colorScheme, 'data-mobile': mobile ? 'true' : 'false', 'data-lazy': lazy ? 'true' : 'false', }; }, [colorScheme, href, numPosts, orderBy, width, mobile, lazy]); return (React.createElement(Parser$1, { className: `fb-comments ${className}`, data: data, ...rest, ref: ref })); } var Comments$1 = React.memo(React.forwardRef(Comments)); function CommentsCount(props, ref) { const { className = '', href = getCurrentHref(), ...rest } = props; const data = React.useMemo(() => { return { 'data-href': href, }; }, [href]); return (React.createElement(Parser$1, { as: "span", className: `fb-comments-count ${className}`, data: data, ...rest, ref: ref })); } var CommentsCount$1 = React.memo(React.forwardRef(CommentsCount)); function Share(props, ref) { const { className = '', href = getCurrentHref(), lazy, layout, size, ...rest } = props; const data = React.useMemo(() => { return { 'data-href': href, 'data-lazy': lazy ? 'true' : 'false', 'data-size': size, 'data-layout': layout, }; }, [href, lazy, size, layout]); return (React.createElement(Parser$1, { className: `fb-share-button ${className}`, data: data, ...rest, ref: ref })); } var Share$1 = React.memo(React.forwardRef(Share)); var LikeSize; (function (LikeSize) { LikeSize["SMALL"] = "small"; LikeSize["LARGE"] = "large"; })(LikeSize || (LikeSize = {})); var LikeSize$1 = LikeSize; var LikeLayout; (function (LikeLayout) { LikeLayout["STANDARD"] = "standard"; LikeLayout["BUTTON_COUNT"] = "button_count"; LikeLayout["BUTTON"] = "button"; LikeLayout["BOX_COUNT"] = "box_count"; })(LikeLayout || (LikeLayout = {})); var LikeLayout$1 = LikeLayout; var ColorScheme; (function (ColorScheme) { ColorScheme["LIGHT"] = "light"; ColorScheme["DARK"] = "dark"; })(ColorScheme || (ColorScheme = {})); var ColorScheme$1 = ColorScheme; var LikeAction; (function (LikeAction) { LikeAction["LIKE"] = "like"; LikeAction["RECOMMEND"] = "recommend"; })(LikeAction || (LikeAction = {})); var LikeAction$1 = LikeAction; var CommentsOrderBy; (function (CommentsOrderBy) { CommentsOrderBy["SOCIAL"] = "social"; CommentsOrderBy["REVERSE_TIME"] = "reverse_time"; CommentsOrderBy["TIME"] = "time"; })(CommentsOrderBy || (CommentsOrderBy = {})); var CommentsOrderBy$1 = CommentsOrderBy; var MessengerSize; (function (MessengerSize) { MessengerSize["SMALL"] = "small"; MessengerSize["MEDIUM"] = "medium"; MessengerSize["STANDARD"] = "standard"; MessengerSize["LARGE"] = "large"; MessengerSize["XLARGE"] = "xlarge"; })(MessengerSize || (MessengerSize = {})); var MessengerSize$1 = MessengerSize; var MessengerColor; (function (MessengerColor) { MessengerColor["BLUE"] = "blue"; MessengerColor["WHITE"] = "white"; })(MessengerColor || (MessengerColor = {})); var MessengerColor$1 = MessengerColor; // @flow // 3.0 fields without app review https://developers.facebook.com/docs/facebook-login/permissions/?locale=en_US#reference-default var Fields = [ 'id', 'first_name', 'last_name', 'middle_name', 'name', 'name_format', 'picture', 'short_name', 'email', ]; /** * Hook for managing Facebook SDK locale dynamically * * @returns Object with current locale, setLocale function, and loading state * * @example * ```tsx * function MyComponent() { * const { locale, setLocale, isChangingLocale } = useLocale(); * * return ( * <div> * <p>Current locale: {locale}</p> * <button * onClick={() => setLocale('es_ES')} * disabled={isChangingLocale} * > * Switch to Spanish * </button> * {isChangingLocale && <p>Changing locale...</p>} * </div> * ); * } * ``` */ function useLocale() { const { locale, setLocale: setFacebookLocale, isLoading } = useFacebook(); const [isChangingLocale, setIsChangingLocale] = React.useState(false); const setLocale = async (newLocale) => { if (newLocale === locale) { return; // No change needed } try { setIsChangingLocale(true); await setFacebookLocale(newLocale); } finally { setIsChangingLocale(false); } }; return { locale: locale, setLocale, isChangingLocale: isChangingLocale || isLoading, availableLocales: [ 'en_US', 'es_ES', 'es_LA', 'fr_FR', 'de_DE', 'it_IT', 'pt_BR', 'pt_PT', 'ja_JP', 'ko_KR', 'zh_CN', 'zh_TW', 'ar_AR', 'hi_IN', 'th_TH', 'vi_VN', 'ru_RU', 'tr_TR', 'pl_PL', 'nl_NL', 'sv_SE', 'da_DK', 'no_NO', 'fi_FI', 'cs_CZ', 'hu_HU', 'ro_RO', 'bg_BG', 'hr_HR', 'sk_SK', 'sl_SI', 'et_EE', 'lv_LV', 'lt_LT', 'uk_UA', 'he_IL', 'af_ZA', 'ms_MY', 'id_ID', 'tl_PH', 'cy_GB', 'eu_ES', 'ca_ES', 'gl_ES' ], }; } function usePixel(props = {}) { const { lazy = false } = props; const context = React.useContext(FacebookPixelContext); if (!context) { throw new Error('usePixel must be used within a FacebookPixelProvider'); } React.useEffect(() => { if (!lazy) { context.init(); } }, [lazy, context.init]); return context; } function usePageView(props = {}) { const { trackOnMount = true, trackOnRouteChange = false } = props; const { pageView, isLoading } = usePixel(); const previousUrlRef = React.useRef(''); React.useEffect(() => { if (trackOnMount && !isLoading) { pageView(); } }, [trackOnMount, isLoading, pageView]); React.useEffect(() => { if (!trackOnRouteChange) return; const currentUrl = window.location.href; if (previousUrlRef.current !== currentUrl) { previousUrlRef.current = currentUrl; if (!isLoading) { pageView(); } } }, [trackOnRouteChange, isLoading, pageView]); return { pageView, isLoading }; } exports.ColorScheme = ColorScheme$1; exports.Comments = Comments$1; exports.CommentsCount = CommentsCount$1; exports.CommentsOrderBy = CommentsOrderBy$1; exports.EmbeddedPost = EmbeddedPost$1; exports.EmbeddedVideo = EmbeddedVideo$1; exports.FacebookContext = FacebookContext; exports.FacebookPixelContext = FacebookPixelContext; exports.FacebookPixelProvider = FacebookPixelProvider; exports.FacebookProvider = FacebookProvider; exports.Fields = Fields; exports.Like = Like$1; exports.LikeAction = LikeAction$1; exports.LikeLayout = LikeLayout$1; exports.LikeSize = LikeSize$1; exports.Login = Login; exports.LoginStatus = LoginStatus$1; exports.MessengerColor = MessengerColor$1; exports.MessengerSize = MessengerSize$1; exports.Page = Page$1; exports.Parser = Parser$1; exports.Share = Share$1; exports.ShareButton = ShareButton; exports.useFacebook = useFacebook; exports.useLocale = useLocale; exports.useLogin = useLogin; exports.useLoginStatus = useLoginStatus; exports.usePageView = usePageView; exports.usePixel = usePixel; exports.useProfile = useProfile; exports.useShare = useShare; exports.useSubscribe = useSubscribe; //# sourceMappingURL=index.js.map