Skip to content

Instantly share code, notes, and snippets.

@arleighdickerson
Created January 21, 2024 00:52
Show Gist options
  • Save arleighdickerson/5afc287820ceef431d4a442548ad406e to your computer and use it in GitHub Desktop.
Save arleighdickerson/5afc287820ceef431d4a442548ad406e to your computer and use it in GitHub Desktop.
Preact Layout -- Patched for V10
// @ts-nocheck
// ¯\_(ツ)_/¯
import { ComponentChildren, ComponentType, Context, h, toChildArray } from 'preact';
function getChildren(node) {
return ((node || {}).props || {}).children;
}
function getComponentType(node) {
return (node || {}).type;
}
function getProps(node) {
return (node || {}).props;
}
function getPropsType(node) {
return (getProps(node) || {}).type;
}
interface LayoutProps {
className?: string;
recurse?: number;
children: ComponentChildren;
}
// noinspection JSUnusedGlobalSymbols
const Layout: ComponentType<LayoutProps> = ({ className, recurse, children, ...props }, context) => {
const { main, sections } = getSections(children);
processNode(main, sections, { ...context }, recurse);
const arr = toChildArray(children);
return children && arr.length === 1 ? arr[0] : <div className={className || 'Layout'}>{children}</div>;
};
interface SectionProps {
type?: ComponentType;
children: ComponentChildren;
}
// noinspection JSUnusedLocalSymbols
const Section: ComponentType<SectionProps> = ({ type, children, ...props }: SectionProps, context: Context<any>) => {
const arr = toChildArray(children);
return children && arr.length === 1 ? arr[0] : <div {...props}>{children}</div>;
};
function getSections(n, result) {
if (!result) result = { sections: [] };
if (getComponentType(n) === Section) {
if (n.props && n.props.type) result.sections.push(n);
else result.main = n;
}
const children = n ? (Array.isArray(n) ? n : getChildren(n)) : undefined;
children &&
toChildArray(children).forEach(c => {
getSections(c, result);
});
return result;
}
function processNode(node, sections, context, recurse, collectOnly, results) {
const leftovers = [],
postProcess = !results;
context = context || {};
if (recurse === undefined) recurse = 9; // arbitrary...
results = results || new Map();
sections.forEach(s => {
if (!getProps(s)) {
return;
}
const propsType = getPropsType(s);
if (!propsType) {
return;
}
results.set(propsType, results.get(propsType) || getChildren(s) || []);
});
getChildren(node) &&
toChildArray(getChildren(node)).forEach(n => {
try {
if (isContribution(n, sections)) {
if (!results.has(n.type)) results.set(n.type, []);
if (n.props && n.props.append) results.get(n.type).push.apply(results.get(n.type), n.props.children || []);
else if (n.props && n.props.prepend)
results.get(n.type).unshift.apply(results.get(n.type), n.props.children || []);
else results.set(n.type, n.props.children || []);
return; // continue
}
leftovers.push(n);
if (getComponentType(n) && recurse) {
let props = { ...getComponentType(n).defaultProps, ...getProps(n), children: getChildren(n) };
if (n.type.prototype && typeof n.type.prototype.render == 'function') {
let c = new n.type(props, context);
c.props = props;
c.context = context;
if (c.componentWillMount) c.componentWillMount();
n = c.render(c.props, c.state, c.context);
if (c.getChildContext) context = { ...context, ...c.getChildContext() };
} else if (typeof n.type === 'string') {
n = h(n.type, props, ...toChildArray(getChildren(props)));
} else {
n = n.type(props, context);
}
recurse--;
}
processNode(n, sections, context, recurse, collectOnly, results);
} catch (e) {
console.error(e);
throw e;
}
});
if (!collectOnly) {
if (getChildren(node)) node.props.children = leftovers;
if (postProcess) sections.forEach(s => (s.props.children = results.get(s.props.type)));
}
return results;
}
function isContribution(n, sections) {
return sections.filter(s => getComponentType(n) === getPropsType(s)).length > 0;
}
export function applyLayout(Layout: ComponentType<any>, Component: ComponentType<any>) {
return (props: any) => h(Layout, props, h(Component, props));
}
export { Layout, Section /* getSections, isContribution, processNode */ };
@arleighdickerson
Copy link
Author

Not my code. I modified it to run for Preact V10. Credits go to https://github.com/download/preact-layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment