Update jdd. Add a linktree-component
This commit is contained in:
parent
ea72b8d016
commit
4569bd5a1a
14
package-lock.json
generated
14
package-lock.json
generated
@ -15,7 +15,7 @@
|
||||
"@sealcode/add-to-head": "^1.0.0",
|
||||
"@sealcode/file-manager": "^1.0.2",
|
||||
"@sealcode/jdd": "^0.8.10",
|
||||
"@sealcode/jdd-editor": "^0.2.30",
|
||||
"@sealcode/jdd-editor": "^0.2.31",
|
||||
"@sealcode/monaco-wrapper": "^0.0.11",
|
||||
"@sealcode/sealgen": "^0.19.21",
|
||||
"@sealcode/show-first-row": "^0.1.0",
|
||||
@ -1380,9 +1380,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sealcode/jdd-editor": {
|
||||
"version": "0.2.30",
|
||||
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.30.tgz",
|
||||
"integrity": "sha512-b+f5xR4FrGc8MLSDKB9AJhehQX8c9NLP7M+towfNUIQNVVVEbecKgJuidmGtSOwrPuahcjRxF8nZqXpFEGdBlQ==",
|
||||
"version": "0.2.31",
|
||||
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.31.tgz",
|
||||
"integrity": "sha512-mPxrh+YGN5q9zSSZU9fjp/M+kTnDb99MGkwEAlcB17dDPJr5enjQJHLMFanC+v/cV5+H7Qxfyj5Yi3+b7ICciQ==",
|
||||
"dependencies": {
|
||||
"@koa/router": "^13.1.0",
|
||||
"@sealcode/jdd": "^0.8.10",
|
||||
@ -16016,9 +16016,9 @@
|
||||
}
|
||||
},
|
||||
"@sealcode/jdd-editor": {
|
||||
"version": "0.2.30",
|
||||
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.30.tgz",
|
||||
"integrity": "sha512-b+f5xR4FrGc8MLSDKB9AJhehQX8c9NLP7M+towfNUIQNVVVEbecKgJuidmGtSOwrPuahcjRxF8nZqXpFEGdBlQ==",
|
||||
"version": "0.2.31",
|
||||
"resolved": "https://registry.npmjs.org/@sealcode/jdd-editor/-/jdd-editor-0.2.31.tgz",
|
||||
"integrity": "sha512-mPxrh+YGN5q9zSSZU9fjp/M+kTnDb99MGkwEAlcB17dDPJr5enjQJHLMFanC+v/cV5+H7Qxfyj5Yi3+b7ICciQ==",
|
||||
"requires": {
|
||||
"@koa/router": "^13.1.0",
|
||||
"@sealcode/jdd": "^0.8.10",
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
"@sealcode/add-to-head": "^1.0.0",
|
||||
"@sealcode/file-manager": "^1.0.2",
|
||||
"@sealcode/jdd": "^0.8.10",
|
||||
"@sealcode/jdd-editor": "^0.2.30",
|
||||
"@sealcode/jdd-editor": "^0.2.31",
|
||||
"@sealcode/monaco-wrapper": "^0.0.11",
|
||||
"@sealcode/sealgen": "^0.19.21",
|
||||
"@sealcode/show-first-row": "^0.1.0",
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
.button {
|
||||
--icon-width: 32px;
|
||||
--gap: 8px;
|
||||
padding: 8px 16px;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
margin: 4px;
|
||||
cursor: pointer;
|
||||
color: var(--button-fg-color);
|
||||
|
||||
&:hover {
|
||||
filter: brightness(1.1);
|
||||
@ -13,14 +19,25 @@
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
svg * {
|
||||
fill: var(--button-fg-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.button--centered {
|
||||
span {
|
||||
text-align: center;
|
||||
margin-right: calc(var(--gap) + var(--icon-width));
|
||||
}
|
||||
}
|
||||
|
||||
.button--color-accent1 {
|
||||
background-color: var(--color-brand-accent);
|
||||
color: var(--color-brand-text-on-accent);
|
||||
--button-fg-color: var(--color-brand-text-on-accent);
|
||||
}
|
||||
|
||||
.button--color-accent2 {
|
||||
background-color: var(--color-brand-accent2);
|
||||
color: var(--color-brand-text-on-accent2);
|
||||
--button-fg-color: var(--color-brand-text-on-accent2);
|
||||
}
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
export const button_variants = ["accent1", "accent2"] as const;
|
||||
type variant = (typeof button_variants)[number];
|
||||
|
||||
export function button({
|
||||
text,
|
||||
href,
|
||||
variant,
|
||||
disabled = false,
|
||||
submit = false,
|
||||
}: {
|
||||
text: string;
|
||||
href: string;
|
||||
variant: variant;
|
||||
disabled?: boolean;
|
||||
submit?: boolean;
|
||||
}): JSX.Element {
|
||||
const classstr = `class="button button--color-${variant}"`;
|
||||
if (submit) {
|
||||
return /* HTML */ `<button type="submit" formaction="${href}" ${classstr}>
|
||||
${text}
|
||||
</button>`;
|
||||
}
|
||||
return /* HTML */ `<a
|
||||
${classstr}
|
||||
${disabled ? "" : `href="${href}"`}
|
||||
${disabled ? "disabled" : ""}
|
||||
>
|
||||
${text}
|
||||
</a>`;
|
||||
}
|
||||
43
src/back/elements/button.tsx
Normal file
43
src/back/elements/button.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { TempstreamJSX } from "tempstream";
|
||||
import { icon as render_icon } from "../icons.js";
|
||||
|
||||
export const button_variants = ["accent1", "accent2"] as const;
|
||||
type variant = (typeof button_variants)[number];
|
||||
|
||||
export function button({
|
||||
text,
|
||||
href,
|
||||
variant,
|
||||
disabled = false,
|
||||
submit = false,
|
||||
icon,
|
||||
centered = false,
|
||||
}: {
|
||||
text: string;
|
||||
href: string;
|
||||
variant: variant;
|
||||
disabled?: boolean;
|
||||
submit?: boolean;
|
||||
icon?: string;
|
||||
centered: boolean;
|
||||
}): JSX.Element {
|
||||
const classstr = `button button--color-${variant}`;
|
||||
if (submit) {
|
||||
return /* HTML */ `<button type="submit" formaction="${href}" ${classstr}>
|
||||
${text}
|
||||
</button>`;
|
||||
}
|
||||
return (
|
||||
<a
|
||||
class={[
|
||||
"button",
|
||||
`button--color-${variant}`,
|
||||
{ "button--centered": centered },
|
||||
]}
|
||||
href={disabled ? false : href}
|
||||
disabled={disabled}
|
||||
>
|
||||
{icon ? render_icon(icon) : ""} <span>{text}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
60
src/back/jdd-components/linktree/linktree.css
Normal file
60
src/back/jdd-components/linktree/linktree.css
Normal file
@ -0,0 +1,60 @@
|
||||
.linktree {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
--image-width: 200px;
|
||||
|
||||
.linktree__photo {
|
||||
picture {
|
||||
border-radius: calc(var(--image-width) / 2);
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
width: var(--image-width) !important;
|
||||
height: var(--image-width) !important;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.linktree__sections {
|
||||
width: max-content;
|
||||
max-width: 100cqw;
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
gap: 8px;
|
||||
justify-content: stretch;
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
a.button {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
min-width: 300px;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/back/jdd-components/linktree/linktree.jdd.tsx
Normal file
69
src/back/jdd-components/linktree/linktree.jdd.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import { TempstreamJSX } from "tempstream";
|
||||
import type { ComponentToHTMLArgs } from "@sealcode/jdd";
|
||||
import { Component, ComponentArguments as Args, insert_nbsp } from "@sealcode/jdd";
|
||||
import { getAllIconNames } from "src/back/icons.js";
|
||||
import { button, button_variants } from "src/back/elements/button.js";
|
||||
|
||||
const component_arguments = {
|
||||
photo: new Args.Image(),
|
||||
title: new Args.ShortText(),
|
||||
description: new Args.Markdown(),
|
||||
sections: new Args.List(
|
||||
new Args.Structured({
|
||||
name: new Args.ShortText(),
|
||||
links: new Args.List(
|
||||
new Args.Structured({
|
||||
href: new Args.URL("absolute"),
|
||||
text: new Args.ShortText(),
|
||||
icon: new Args.Enum(getAllIconNames),
|
||||
variant: new Args.Enum(button_variants),
|
||||
})
|
||||
),
|
||||
})
|
||||
),
|
||||
} as const;
|
||||
|
||||
export class Linktree extends Component<typeof component_arguments> {
|
||||
getArguments() {
|
||||
return component_arguments;
|
||||
}
|
||||
|
||||
async toHTML({
|
||||
args: { photo, title, description, sections },
|
||||
classes,
|
||||
jdd_context: { render_markdown, render_image, language },
|
||||
}: ComponentToHTMLArgs<typeof component_arguments>): Promise<string> {
|
||||
return (
|
||||
<div class={["linktree", ...classes]}>
|
||||
<div class="linktree__photo">
|
||||
{photo
|
||||
? render_image(photo, {
|
||||
sizesAttr: "200px",
|
||||
|
||||
container: {
|
||||
width: 200,
|
||||
height: 200,
|
||||
objectFit: "cover",
|
||||
},
|
||||
alt: title || "",
|
||||
})
|
||||
: ""}
|
||||
</div>
|
||||
{title ? <h2>{insert_nbsp(title)}</h2> : ""}
|
||||
{description ? <div>{render_markdown(language, description)}</div> : ""}
|
||||
<div class="linktree__sections">
|
||||
{sections.map((section) => (
|
||||
/* HTML */ <section>
|
||||
<h3>{section.name}</h3>
|
||||
<ul>
|
||||
{section.links.map((link) => (
|
||||
<li>{button({ ...link, centered: true })}</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user