import { render, renderEarlyAssets } from "@sealcode/jdd"; import { StatefulPage, to_base64 } from "@sealcode/sealgen"; import { hasShape, predicates } from "@sealcode/ts-predicates"; import { BaseContext } from "koa"; import { Templatable, tempstream, TempstreamJSX } from "tempstream"; import html, { defaultHead } from "../html.js"; import { registry } from "../jdd-components/components.js"; import { ComponentInput } from "./component-preview/component-input.js"; import { ComponentPreviewActions } from "./component-preview/component-preview-actions.js"; import { jdd_context } from "./jdd-context.js"; export const actionName = "Components"; export type ComponentPreviewState = { component: string; component_args: Record; }; export default new (class ComponentsPage extends StatefulPage< ComponentPreviewState, typeof ComponentPreviewActions > { actions = ComponentPreviewActions; async getInitialState() { const [component_name, component] = Object.entries(registry.getAll())[0]; const initial_state = { component: component_name, component_args: await component.getExampleValues(jdd_context), }; return initial_state; } wrapInLayout( ctx: BaseContext, content: Templatable, state: ComponentPreviewState ): Templatable { return html( ctx, "Components", content, { morphing: true, preserveScroll: true, autoRefreshCSS: true, navbar: () => ``, }, (...args) => tempstream`${defaultHead(...args)}${renderEarlyAssets( registry, [ { component_name: state.component, args: state.component_args, }, ], jdd_context )}` ); } wrapInForm(state: ComponentPreviewState, content: Templatable): Templatable { // overwriting this method in order to add enctype to form return (
{content}
); } async preprocessOverrides( state: ComponentPreviewState, overrides: Record ) { const component_name = state.component; if (!component_name) { throw new Error("Unspecified component name"); } const component = registry.get(component_name); if (!component) { throw new Error(`Unknown component: ${component_name}`); } if (!hasShape({ component_args: predicates.object }, overrides)) { return overrides; } const promises = Object.entries(component.getArguments()).map( async ([arg_name, arg]) => { const value = overrides.component_args[arg_name]; if (value) { const new_value = await arg.parseFormInput( jdd_context, value, arg_name ); overrides.component_args[arg_name] = new_value; } } ); await Promise.all(promises); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions return overrides; } render(_ctx: BaseContext, state: ComponentPreviewState) { const all_components = registry.getAll(); const component = registry.get(state.component) || Object.values(all_components)[0]; return (
{/*The below button has to be here in order for it to be the default behavior */} {this.makeActionButton(state, "randomize_args")}
Parameters {Object.entries(component.getArguments()).map( async ([arg_name, arg]) => ( ) )}
{JSON.stringify(state)}
Preview{" "} {render( registry, [ { component_name: state.component, args: state.component_args, }, ], jdd_context )}
{ /* HTML */ `` }
); } })();