frontend-hamroun
Version:
A lightweight frontend JavaScript framework with React-like syntax
105 lines (103 loc) • 3.8 kB
JavaScript
function jsx(type, props) {
console.log('JSX Transform:', { type, props });
const processedProps = { ...props };
// Handle children properly
if (arguments.length > 2) {
processedProps.children = Array.prototype.slice.call(arguments, 2);
}
return { type, props: processedProps };
}
const Fragment = ({ children }) => children;
async function createElement(vnode) {
console.log('Creating element from:', vnode);
// Handle primitives and null
if (vnode == null) {
return document.createTextNode('');
}
if (typeof vnode === 'boolean') {
return document.createTextNode('');
}
if (typeof vnode === 'number' || typeof vnode === 'string') {
return document.createTextNode(String(vnode));
}
// Handle arrays
if (Array.isArray(vnode)) {
const fragment = document.createDocumentFragment();
for (const child of vnode) {
const node = await createElement(child);
fragment.appendChild(node);
}
return fragment;
}
// Handle VNode
if ('type' in vnode && vnode.props !== undefined) {
const { type, props } = vnode;
// Handle function components
if (typeof type === 'function') {
try {
const result = await type(props || {});
const node = await createElement(result);
if (node instanceof Element) {
node.setAttribute('data-component-id', type.name || type.toString());
}
return node;
}
catch (error) {
console.error('Error rendering component:', error);
return document.createTextNode('');
}
}
// Create DOM element
const element = document.createElement(type);
// Handle props
for (const [key, value] of Object.entries(props || {})) {
if (key === 'children')
continue;
if (key.startsWith('on') && typeof value === 'function') {
const eventName = key.toLowerCase().slice(2);
// Remove existing event listener if any
const existingHandler = element.__events?.[eventName];
if (existingHandler) {
element.removeEventListener(eventName, existingHandler);
}
// Add new event listener
element.addEventListener(eventName, value);
if (!element.__events) {
element.__events = {};
}
element.__events[eventName] = value;
}
else if (key === 'style' && typeof value === 'object') {
Object.assign(element.style, value);
}
else if (key === 'className') {
element.setAttribute('class', String(value));
}
else if (key !== 'key' && key !== 'ref') {
element.setAttribute(key, String(value));
}
}
// Handle children
const children = props?.children;
if (children != null) {
const childArray = Array.isArray(children) ? children.flat() : [children];
for (const child of childArray) {
const childNode = await createElement(child);
element.appendChild(childNode);
}
}
return element;
}
// Handle other objects by converting to string
return document.createTextNode(String(vnode));
}
// Named exports object
const jsxRuntime = {
jsx,
jsxs: jsx,
jsxDEV: jsx,
Fragment,
createElement
};
export { Fragment, createElement, jsxRuntime as default, jsx, jsx as jsxDEV, jsx as jsxs };
//# sourceMappingURL=jsx-runtime.js.map