react-native-wishlist
Version:
The fastest List component for React Native.
183 lines (177 loc) • 7.7 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createTemplateComponent = createTemplateComponent;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _EventHandler = require("./EventHandler");
var _ForEachBase = require("./Components/ForEachBase");
var _InflatorRepository = _interopRequireDefault(require("./InflatorRepository"));
var _Switch = require("./Components/Switch");
var _TemplateContext = require("./TemplateContext");
var _TemplateValue = require("./TemplateValue");
var _Utils = require("./Utils");
var _WishlistContext = require("./WishlistContext");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function setInObject(obj, path, value) {
'worklet';
let current = obj;
for (let i = 0; i < path.length - 1; i++) {
current[path[i]] = current[path[i]] ?? {};
current = current[path[i]];
}
current[path[path.length - 1]] = value;
}
function traverseObject(obj, callback) {
const stack = [{
path: [],
value: obj
}];
while (stack.length > 0) {
const {
path,
value
} = stack.pop();
if (value && typeof value === 'object' && !(0, _TemplateValue.isTemplateValue)(value) && !(value instanceof _EventHandler.TemplateCallback) && (path.length === 0 || path[path.length - 1] !== 'children')) {
Object.keys(value).forEach(key => {
stack.push({
path: [...path, key],
value: value[key]
});
});
} else {
callback(path, value);
}
}
}
function convertToTemplateValue(value, path) {
let curTemplateType = value;
return {
// TODO(janic): Need to call remove for template values created here.
templateValue: (0, _TemplateValue.createTemplateValue)(() => {
'worklet';
return curTemplateType;
}),
targetPath: path
};
}
function createTemplateComponent(Component, addProps) {
const WishListComponent = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
let {
style,
...props
} = _ref;
const {
inflatorId
} = (0, _WishlistContext.useWishlistContext)();
const {
templateType
} = (0, _TemplateContext.useTemplateContext)();
const nativeId = (0, _react.useMemo)(_Utils.generateId, []);
const otherPropsMemoized = (0, _react.useMemo)(() => {
const resolvedStyle = _reactNative.StyleSheet.flatten(style);
const templateValues = [];
const templateCallbacks = [];
const otherProps = {};
traverseObject({
...props,
style: resolvedStyle
}, (path, value) => {
const applyHacks = () => {
// Text component needs to receive a string child to work properly.
// @ts-expect-error TODO: fix this.
if (path[0] === 'children' && Component === _reactNative.Text) {
setInObject(otherProps, path, ' ');
}
};
if ((0, _TemplateValue.isTemplateValue)(value)) {
templateValues.push({
templateValue: value,
targetPath: path
});
applyHacks();
} else if (value instanceof _EventHandler.TemplateCallback) {
templateCallbacks.push({
worklet: value.worklet,
// Callbacks should never be in objects.
eventName: value.eventName ?? path[0].replace(/^on/, 'top')
});
// Events have a boolean prop associated to know whether the
// function is set or not, so we still want to pass the prop.
setInObject(otherProps, path, () => {});
} else {
// @ts-expect-error TODO: fix this.
if (Component === _ForEachBase.ForEachBase && path[0] === 'template') {
templateValues.push(convertToTemplateValue(value, path));
}
if (
// @ts-expect-error TODO: fix this.
Component === _Switch.CaseBase && path[0] === 'value' && !(0, _TemplateValue.isTemplateValue)(value)) {
templateValues.push(convertToTemplateValue(value, path));
}
if (
// @ts-expect-error TODO: fix this.
Component === _reactNative.Text && path[0] === 'children' && !(0, _TemplateValue.isTemplateValue)(value)) {
templateValues.push(convertToTemplateValue(value, path));
}
setInObject(otherProps, path, value);
}
});
_InflatorRepository.default.registerMapping(inflatorId, nativeId, templateType, (value, templateItem, pool, rootValue) => {
'worklet';
templateValues.forEach(_ref2 => {
let {
templateValue
} = _ref2;
templateValue.__setDirty();
});
const propsToSet = {};
templateValues.forEach(_ref3 => {
let {
templateValue,
targetPath
} = _ref3;
setInObject(propsToSet, targetPath, templateValue.value());
});
templateCallbacks.forEach(_ref4 => {
let {
eventName,
worklet
} = _ref4;
templateItem.setCallback(eventName, ev => {
worklet(ev, value, rootValue);
});
});
// Styles need to be passed as props.
const {
style: styleForProps,
...otherPropsToSet
} = propsToSet;
const finalPropsToSet = {
...otherPropsToSet,
...styleForProps
};
if (addProps) {
addProps(templateItem, finalPropsToSet, inflatorId, pool, rootValue);
} else {
templateItem.addProps(finalPropsToSet);
}
});
return otherProps;
// TODO: This will change on every render, if we want this memo to work properly we need
// to shallow compare the props object.
}, [inflatorId, nativeId, props, style, templateType]);
// @ts-expect-error: this is ok.
return /*#__PURE__*/_react.default.createElement(Component, _extends({}, otherPropsMemoized, {
ref: ref,
nativeID: nativeId
}));
});
WishListComponent.displayName = `WishList(${Component.displayName})`;
return WishListComponent;
}
//# sourceMappingURL=createTemplateComponent.js.map
;