/** @jsxImportSource react */ import { Widget, VDOM, getContent } from "../ui/Widget"; import { ChildNode, ContainerBase, StyledContainerConfig } from "../ui/Container"; import { Heading } from "./Heading"; import { isString } from "../util/isString"; import { parseStyle } from "../util/parseStyle"; import { RenderingContext } from "../ui/RenderingContext"; import { Instance } from "../ui/Instance"; import { BooleanProp, StringProp, StyleProp, ClassProp, Prop } from "../ui/Prop"; import { Create } from "../util/Component"; export interface SectionConfig extends StyledContainerConfig { id?: Prop; /** Add default padding to the section body. Default is `true`. */ pad?: BooleanProp; /** A custom style which will be applied to the header. */ headerStyle?: StyleProp; /** Additional CSS class to be applied to the header. */ headerClass?: ClassProp; /** A custom style which will be applied to the body. */ bodyStyle?: StyleProp; /** Additional CSS class to be applied to the section body. */ bodyClass?: ClassProp; /** A custom style which will be applied to the footer. */ footerStyle?: StyleProp; /** Additional CSS class to be applied to the footer. */ footerClass?: ClassProp; /** Section's title. */ title?: StringProp; /** Contents that should go in the header. */ header?: Create; /** Contents that should go in the footer. */ footer?: Create; /** Title heading level (1-6) */ hLevel?: number; } export class Section extends ContainerBase { declare headerStyle?: StyleProp; declare footerStyle?: StyleProp; declare bodyStyle?: StyleProp; declare title?: StringProp; declare header?: Create; declare footer?: Create; declare hLevel?: number; declare pad?: BooleanProp; declare baseClass: string; init(): void { if (isString(this.headerStyle)) this.headerStyle = parseStyle(this.headerStyle); if (isString(this.footerStyle)) this.footerStyle = parseStyle(this.footerStyle); if (isString(this.bodyStyle)) this.bodyStyle = parseStyle(this.bodyStyle); super.init(); } add(item: any): void { if (item && item.putInto == "header") this.header = { ...item, putInto: null, }; else if (item && item.putInto == "footer") this.footer = { ...item, putInto: null, }; else super.add(item); } declareData(...args: Record[]): void { super.declareData(...args, { id: undefined, headerStyle: { structured: true }, headerClass: { structured: true }, bodyStyle: { structured: true }, bodyClass: { structured: true }, footerStyle: { structured: true }, footerClass: { structured: true }, }); } initComponents(context: RenderingContext, instance: Instance): void { super.initComponents(context, instance, { header: this.getHeader(), footer: this.getFooter(), }); } getHeader(): Widget | null { if (this.title) return Widget.create(Heading, { text: this.title, level: this.hLevel, }) as Widget; if (this.header) return Heading.create(this.header); return null; } getFooter(): Widget | null { if (this.footer) return Widget.create(this.footer); return null; } prepareData(context: RenderingContext, instance: Instance): void { let { data } = instance; data.stateMods = { ...data.stateMods, pad: this.pad, }; super.prepareData(context, instance); } initInstance(context: RenderingContext, instance: Instance): void { (instance as any).eventHandlers = instance.getJsxEventProps(); super.initInstance(context, instance); } render(context: RenderingContext, instance: Instance, key: string): React.ReactNode { let { data, components } = instance; let eventHandlers = (instance as any).eventHandlers; let header: React.ReactNode, footer: React.ReactNode; let { CSS, baseClass } = this; if (components?.header) { header = (
{getContent(components.header.render(context))}
); } if (components?.footer) { footer = (
{getContent(components.footer.render(context))}
); } return (
{header}
{this.renderChildren(context, instance)}
{footer}
); } } Section.prototype.styled = true; Section.prototype.pad = true; Section.prototype.baseClass = "section"; Section.prototype.hLevel = 3;