react-facebook
Version:
Facebook components like a Login button, Like, Share, Comments, Embedded Post/Video, Messenger Chat, and Facebook Pixel tracking
1,169 lines (1,131 loc) • 39.2 kB
JavaScript
import React, { createContext, useState, useRef, useEffect, useContext, memo, forwardRef, useCallback, useMemo } from '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 = 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 = createContext(undefined);
function FacebookPixelProvider(props) {
const { children, lazy = false, ...options } = props;
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState();
const pixelRef = useRef();
const initPromiseRef = 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));
}
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] = useState(true);
const [isReady, setIsReady] = useState(false);
const [error, setError] = useState();
const [locale, setLocaleState] = useState(options.language || 'en_US');
const apiRef = useRef();
const initPromiseRef = 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);
}
}
useEffect(() => {
const { lazy } = options;
if (!lazy) {
init();
}
}, [options.lazy]);
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 = useContext(FacebookContext);
if (!context) {
throw new Error('useFacebook must be used within a FacebookProvider');
}
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] = useState(null);
const handleRef = useCallback((element) => {
setElement(element);
if (forwardedRef) {
if (typeof forwardedRef === 'function') {
forwardedRef(element);
}
else if (forwardedRef) {
forwardedRef.current = element;
}
}
}, [forwardedRef]);
const key = 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]);
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 = memo(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 = 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 = memo(forwardRef(Like));
function clearUndefinedProperties(obj) {
return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
}
function useShare() {
const { init } = useFacebook();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = 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 = 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 = memo(forwardRef(Page));
function useLogin() {
const { api, isLoading } = useFacebook();
const [error, setError] = useState(undefined);
const [isLoadingLogin, setIsLoadingLogin] = useState(false);
const [latestResponse, setLatestResponse] = 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] = useState(undefined);
const { init } = useFacebook();
const handleResponse = useCallback((value) => {
setLastValue(value);
callback === null || callback === void 0 ? void 0 : callback(value);
}, [callback]);
const handleSubscribe = useCallback(async () => {
const api = await init();
if (api) {
await api.subscribe(event, handleResponse);
}
}, [event, handleResponse, init]);
const handleUnsubscribe = useCallback(async () => {
const api = await init();
if (api) {
await api.unsubscribe(event, handleResponse);
}
}, [event, handleResponse, init]);
useEffect(() => {
handleSubscribe();
return () => {
handleUnsubscribe();
};
}, [handleSubscribe, handleUnsubscribe]);
return lastValue;
}
function useLoginStatus() {
const { init } = useFacebook();
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(undefined);
const [status, setStatus] = useState(LoginStatus$1.UNKNOWN);
const handleStatusChanges = 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);
}
}
useEffect(() => {
handleGetInitState();
}, []);
return {
isLoading,
error,
status,
};
}
function useProfile(fields) {
const { init } = useFacebook();
const { status } = useLoginStatus();
const [isLoading, setIsLoading] = useState(true);
const [profile, setProfile] = useState(undefined);
const [error, setError] = 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);
}
}
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);
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 = 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 = memo(forwardRef(EmbeddedPost));
function EmbeddedVideo(props, ref) {
const { className = '', href, width, showText, allowFullScreen, autoPlay, lazy, showCaptions, ...rest } = props;
const data = 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 = memo(forwardRef(EmbeddedVideo));
function Comments(props, ref) {
const { className = '', colorScheme, href = getCurrentHref(), numPosts, orderBy, width, mobile, lazy, ...rest } = props;
const data = 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 = memo(forwardRef(Comments));
function CommentsCount(props, ref) {
const { className = '', href = getCurrentHref(), ...rest } = props;
const data = 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 = memo(forwardRef(CommentsCount));
function Share(props, ref) {
const { className = '', href = getCurrentHref(), lazy, layout, size, ...rest } = props;
const data = 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 = memo(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] = 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 = useContext(FacebookPixelContext);
if (!context) {
throw new Error('usePixel must be used within a FacebookPixelProvider');
}
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 = useRef('');
useEffect(() => {
if (trackOnMount && !isLoading) {
pageView();
}
}, [trackOnMount, isLoading, pageView]);
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 };
}
export { ColorScheme$1 as ColorScheme, Comments$1 as Comments, CommentsCount$1 as CommentsCount, CommentsOrderBy$1 as CommentsOrderBy, EmbeddedPost$1 as EmbeddedPost, EmbeddedVideo$1 as EmbeddedVideo, FacebookContext, FacebookPixelContext, FacebookPixelProvider, FacebookProvider, Fields, Like$1 as Like, LikeAction$1 as LikeAction, LikeLayout$1 as LikeLayout, LikeSize$1 as LikeSize, Login, LoginStatus$1 as LoginStatus, MessengerColor$1 as MessengerColor, MessengerSize$1 as MessengerSize, Page$1 as Page, Parser$1 as Parser, Share$1 as Share, ShareButton, useFacebook, useLocale, useLogin, useLoginStatus, usePageView, usePixel, useProfile, useShare, useSubscribe };
//# sourceMappingURL=index.js.map