Last active
August 19, 2024 23:50
-
-
Save arleighdickerson/5afc287820ceef431d4a442548ad406e to your computer and use it in GitHub Desktop.
Preact Layout -- Patched for V10
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @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 */ }; | |
export const NavBar: ComponentType = (() => {}) as any; | |
export const Header: ComponentType = (() => {}) as any; | |
export const BreadCrumbs: ComponentType = (() => {}) as any; | |
export const Left: ComponentType = (() => {}) as any; | |
export const Right: ComponentType = (() => {}) as any; | |
export const Footer: ComponentType = (() => {}) as any; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Not my code. I modified it to run for Preact V10. Credits go to https://github.com/download/preact-layout