@applicaster/zapp-react-native-ui-components
Version:
Applicaster Zapp React Native ui components for the Quick Brick App
104 lines (88 loc) • 3.25 kB
text/typescript
import * as R from "ramda";
import { isFunction } from "@applicaster/zapp-react-native-utils/functionUtils";
import { functionForName } from "./MappingFunctions";
import { resolveColor } from "./utils";
/**
* Uses passed function or retrieves function according to func name,
* and performs the function on the entry with the provided args.
* @param {Object} entry Single entry of a feed
* @param {String | Function} func Func name or custom function
* @param {Array} args Additional arguments for the function
*/
function retrieveData(entry, func, args) {
if (R.isNil(func)) {
throw new Error(
"Missing func in the data mapping, please revise or update cell styles configuration"
);
}
const funcToUse = isFunction(func) ? func : functionForName(func);
return funcToUse(entry, args);
}
/**
* Inflates the provided masterCell configuration with the data coming from a datasource entry
* curried function of the form configInflater(entry)(masterCellConfig)
* @param {Object} entry from the data source
* @param {Object} masterCellConfig master cell configuration coming from zapp
* @param {String} masterCellConfig.type of the component
* @param {Object} masterCellConfig.style default style object for the component
* @param {?Object} masterCellConfig.data func/args/propName that indicates how to extract
* the data from the entry and to which prop it should be injected after manipulation
* @param {?[Object]} element.elements Optional array of nested elements to render within the current node
* @returns {Object} inflated configuration, ready to be rendered by the master cell's element mapper
*/
export function configInflater(
entry: any,
{
type,
style,
additionalProps = {},
data = [],
elements,
}: {
type: any;
style: any;
additionalProps?: Record<string, any>;
data?: Array<{ propName: string; func: Function; args: any[] }>;
elements?: any[];
}
) {
const props = data.reduce(
(acc, curr) => {
acc[curr.propName] = retrieveData(entry, curr.func, curr.args);
return acc;
},
{ ...additionalProps }
);
let adjustedElements;
if (Array.isArray(elements)) {
adjustedElements = elements.map((element) =>
configInflater(entry, element as any)
);
}
return {
type,
style: resolveColor(entry, style),
props,
elements: adjustedElements,
};
}
/**
* Return the proper view tree according to entry's content type and UI state.
* Falls back to "default" content type or state.
* @param {Object} entry data source feed entry
* @param {"selected" | "focused" | ...} state of the current cell
* @param {Object} elements master cell configuration
*/
function resolveElementsNode(entry, state, elements) {
const contentType = entry?.type?.value;
const contentTypeElement =
elements.content_types[contentType] || elements.content_types.default;
return contentTypeElement.states[state] || contentTypeElement.states.default;
}
export function defaultDataAdapter(elements) {
return function elementsBuilder({ entry, state = "default" }) {
return resolveElementsNode(entry, state, elements).map((element) =>
configInflater(entry, element)
);
};
}