@bloomreach/react-sdk
Version:
Bloomreach SPA SDK for React
320 lines (293 loc) • 12.4 kB
JavaScript
import React, { useRef, useEffect, useState, useCallback } from "react";
import { TYPE_MANAGE_CONTENT_BUTTON, TYPE_MANAGE_MENU_BUTTON, TYPE_CONTAINER_UNORDERED_LIST, TYPE_CONTAINER_ORDERED_LIST, TYPE_CONTAINER_NO_MARKUP, TYPE_CONTAINER_INLINE, TYPE_CONTAINER_ITEM_UNDEFINED, isContainer, isContainerItem, initialize } from "@bloomreach/spa-sdk";
function BrMeta({children, meta}) {
var _a;
const head = useRef(null);
const tail = useRef(null);
useEffect((() => {
var _a;
if (!((_a = head.current) === null || _a === void 0 ? void 0 : _a.nextSibling) || !tail.current) {
return undefined;
}
return meta === null || meta === void 0 ? void 0 : meta.render(head.current.nextSibling, tail.current);
}), [ meta, (_a = head.current) === null || _a === void 0 ? void 0 : _a.nextSibling, tail.current ]);
return React.createElement(React.Fragment, null, meta && meta.length > 0 && React.createElement("span", {
style: {
display: "none"
},
ref: head
}), children, meta && meta.length > 0 && React.createElement("span", {
style: {
display: "none"
},
ref: tail
}));
}
function BrContainerBox({page, children}) {
return React.createElement("div", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container" : undefined
}, React.Children.map(children, (child => React.createElement("div", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container-item" : undefined
}, child))));
}
function BrContainerInline(props) {
const {page, children} = props;
return React.createElement("div", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container" : undefined
}, React.Children.map(children, (child => React.createElement("span", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container-item" : undefined
}, child))));
}
function BrContainerNoMarkup({children}) {
return React.createElement(React.Fragment, null, children);
}
function BrContainerOrderedList({page, children}) {
return React.createElement("ol", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container" : undefined
}, React.Children.map(children, (child => React.createElement("li", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container-item" : undefined
}, child))));
}
function BrContainerUnorderedList({page, children}) {
return React.createElement("ul", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container" : undefined
}, React.Children.map(children, (child => React.createElement("li", {
className: (page === null || page === void 0 ? void 0 : page.isPreview()) ? "hst-container-item" : undefined
}, child))));
}
function BrContainerItemUndefined({component}) {
return React.createElement("div", null, `Component "${component === null || component === void 0 ? void 0 : component.getType()}" is not defined.`);
}
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */ function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P((function(resolve) {
resolve(value);
}));
}
return new (P || (P = Promise))((function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
}));
}
typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* The button component that opens for editing a content.
*/ function BrManageContentButton(props) {
const {page} = props, buttonProps = __rest(props, [ "page" ]);
return page.isPreview() ? React.createElement(BrMeta, {
meta: page.getButton(TYPE_MANAGE_CONTENT_BUTTON, buttonProps)
}) : React.createElement(React.Fragment, null);
}
/**
* The button component that opens a menu editor.
*/ function BrManageMenuButton({page, menu}) {
return page.isPreview() ? React.createElement(BrMeta, {
meta: page.getButton(TYPE_MANAGE_MENU_BUTTON, menu)
}) : React.createElement(React.Fragment, null);
}
/**
* Node container component for rendering brXM container components with prop-based mapping.
*/ function BrNodeContainer(props) {
const {component, mapping, children} = props;
const getMapping = () => {
const type = component.getType();
if (type && type in mapping) {
return mapping[type];
}
switch (type) {
case TYPE_CONTAINER_INLINE:
return BrContainerInline;
case TYPE_CONTAINER_NO_MARKUP:
return BrContainerNoMarkup;
case TYPE_CONTAINER_ORDERED_LIST:
return BrContainerOrderedList;
case TYPE_CONTAINER_UNORDERED_LIST:
return BrContainerUnorderedList;
default:
return BrContainerBox;
}
};
const containerMapping = getMapping();
const meta = component.getMeta();
const content = containerMapping ? React.createElement(containerMapping, props) : children;
return React.createElement(BrMeta, {
meta
}, content);
}
/**
* Node container item component for rendering brXM container items with prop-based mapping.
*/ function BrNodeContainerItem(props) {
const {component, page, mapping, children} = props;
const [forcedRerenders, setForcedRerenders] = useState(0);
const onUpdate = useCallback((() => {
setForcedRerenders((c => c + 1));
}), []);
useEffect((() => {
component === null || component === void 0 ? void 0 : component.on("update", onUpdate);
return () => {
component === null || component === void 0 ? void 0 : component.off("update", onUpdate);
};
}), [ component, onUpdate ]);
useEffect((() => {
if (forcedRerenders > 0) {
page === null || page === void 0 ? void 0 : page.sync();
}
}), [ page, forcedRerenders ]);
const getMapping = () => {
var _a;
const type = component === null || component === void 0 ? void 0 : component.getType();
if (type && type in mapping) {
return mapping[type];
}
return (_a = mapping[TYPE_CONTAINER_ITEM_UNDEFINED]) !== null && _a !== void 0 ? _a : BrContainerItemUndefined;
};
const containerItemMapping = getMapping();
const meta = component === null || component === void 0 ? void 0 : component.getMeta();
const content = containerItemMapping ? React.createElement(containerItemMapping, props) : children;
return React.createElement(BrMeta, {
meta
}, content);
}
/**
* Node component for rendering brXM components with prop-based mapping resolution.
*/ function BrNodeComponent(props) {
const {component, mapping, children} = props;
const componentName = component === null || component === void 0 ? void 0 : component.getName();
const resolvedMapping = component && componentName && mapping[componentName];
const meta = component === null || component === void 0 ? void 0 : component.getMeta();
const content = resolvedMapping ? React.createElement(resolvedMapping, props) : children;
return React.createElement(BrMeta, {
meta
}, content);
}
/**
* Core node component for rendering brXM components with prop drilling.
*/ function BrNode({children, component, page, mapping}) {
if (React.Children.count(children)) {
return React.createElement(BrMeta, {
meta: component.getMeta()
}, children);
}
const props = {
page,
mapping
};
const childrenList = component.getChildren().map((child => React.createElement(BrNode, Object.assign({
key: child.getId(),
component: child
}, props))));
if (isContainer(component)) {
return React.createElement(BrNodeContainer, Object.assign({
component
}, props), childrenList);
}
if (isContainerItem(component)) {
return React.createElement(BrNodeContainerItem, Object.assign({
component
}, props), childrenList);
}
return React.createElement(BrNodeComponent, Object.assign({
component
}, props), childrenList);
}
/**
* The brXM component with prop-based data access.
*/ function BrComponent({path, children, component, page, mapping}) {
function getComponents() {
if (!path) {
return component.getChildren();
}
const targetComponent = component.getComponent(...path.split("/"));
return targetComponent ? [ targetComponent ] : [];
}
function renderComponents() {
return getComponents().map((comp => React.createElement(BrNode, {
key: comp.getId(),
component: comp,
page,
mapping
}, typeof children === "function" ? children({
page,
component: comp,
mapping
}) : children)));
}
return React.createElement(React.Fragment, null, renderComponents());
}
/**
* The brXM page component with React Server Components (RSC) support.
*/ function BrPage({configuration, mapping, page: initialPage, children}) {
const [page, setPage] = useState((() => initialPage ? initialize(configuration, initialPage) : undefined));
useEffect((() => {
let isMounted = true;
const initializePage = () => __awaiter(this, void 0, void 0, (function*() {
const newPage = initialPage ? initialize(configuration, initialPage) : yield initialize(configuration);
if (isMounted) {
setPage(newPage);
}
}));
initializePage();
return () => {
isMounted = false;
};
}), [ configuration, initialPage ]);
useEffect((() => {
page === null || page === void 0 ? void 0 : page.sync();
}), [ page ]);
if (!page) {
if (configuration.NBRMode) {
return React.createElement(React.Fragment, null, children);
}
return null;
}
const component = page.getComponent();
return React.createElement(BrNode, {
page,
mapping,
component
}, typeof children === "function" ? children({
page,
component,
mapping
}) : children);
}
export { BrComponent, BrManageContentButton, BrManageMenuButton, BrPage };
//# sourceMappingURL=index.js.map