127 lines
3.3 KiB
TypeScript

import { TempstreamJSX } from "tempstream";
import type {
ComponentToHTMLArgs,
ExtractStructuredComponentArgumentsParsed,
JDDContext,
} from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
import { horizontalScroller } from "src/back/routes/common/horizontal-scroller/horizontal-scroller.js";
import { getColorVariables, getFgColorVariable } from "src/back/colors.js";
import { icon } from "src/back/icons.js";
const component_arguments = {
mode: new ComponentArguments.Enum(["column", "horizontal-scroller"]).setDefaultValue(
"column"
),
scroller_mode_item_width: new ComponentArguments.Number().setDefaultValue(320),
scroller_mode_arrows_color: new ComponentArguments.Enum(
getColorVariables()
).setDefaultValue("--color-brand-accent"),
bleed: new ComponentArguments.Enum(["none", "bleed", "screen"]).setDefaultValue(
"none"
),
gap: new ComponentArguments.Enum([
"none",
"narrow",
"medium",
"wide",
]).setDefaultValue("medium"),
padding_vertical: new ComponentArguments.Enum([
"none",
"narrow",
"medium",
"wide",
"extra-wide",
"super-wide",
]).setDefaultValue("medium"),
components: new ComponentArguments.List(new ComponentArguments.NestedComponent()),
} as const;
export class Subtree extends Component<typeof component_arguments> {
getArguments() {
return component_arguments;
}
getCSSClumps(
jdd_context: JDDContext,
args: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>
) {
const result = (args.components || [])
.map((component) => component.getCSSClumps(jdd_context))
.flat();
return result;
}
async toHTML({
args: {
mode,
components,
gap,
padding_vertical,
bleed,
scroller_mode_item_width,
scroller_mode_arrows_color,
},
classes,
jdd_context,
}: ComponentToHTMLArgs<typeof component_arguments>): Promise<string> {
const cls = [
"subtree",
`subtree--gap-${gap}`,
`subtree--padding-vertical-${padding_vertical}`,
`subtree--mode-${mode}`,
`subtree--bleed-${bleed}`,
...classes,
];
if (mode == "horizontal-scroller") {
const button_styles = [
`background-color: var(${scroller_mode_arrows_color})`,
`--fg-color: var(${getFgColorVariable(scroller_mode_arrows_color)})`,
].join(";");
return (
<div
class={cls}
style={`--horizontal-scroller-item-width: ${scroller_mode_item_width}px;`}
>
{horizontalScroller({
render: async ({ scroller, markers }) => (
<div class="scroller-wrapper">
<div class="button-panel button-panel--left">
<button
class="button prev-button"
type="button"
data-action="horizontal-scroller#scrollLeft"
style={button_styles}
>
{icon("arrow-left")}
</button>
</div>
<div class="button-panel button-panel--right">
<button
class="button next-button"
type="button"
data-action="horizontal-scroller#scrollRight"
style={button_styles}
>
{icon("arrow-right")}
</button>
</div>
{scroller}
{markers}
</div>
),
elements: components?.map((component) =>
component.render(jdd_context)
),
})}
</div>
);
}
return (
<div class={cls}>
{components?.map((component) => component.render(jdd_context))}
</div>
);
}
}