feat: zooweemama

This commit is contained in:
TrèsAbhi committed 2026-03-19 13:26:34 -05:00
1 parent 841b5708ae
commit 824169fc25
7 files changed
+97 -26

No files matched your search

@@ -0,0 +1,58 @@
---
import ApiMacroSee from "./ApiMacroSee.astro";
import { MarkdownCustom } from "./MarkdownCustom";
interface Props {
body: string;
}
const macroPattern = /@(\w+) (.+)/;
const macros: Record<string, string> = {};
const { body: bodyOriginal } = Astro.props;
let body = "";
for (const line of bodyOriginal.split("\n")) {
const match = line.match(macroPattern);
if (match === null) {
body += `${line}\n`;
continue;
}
const macro = match[1];
const value = match[2];
macros[macro] = value;
}
---
<style>
.api-description {
display: flex;
.gutter {
width: var(--space-2);
background: linear-gradient(transparent, var(--gray-6) var(--space-4));
margin: 0 var(--space-4);
}
.content {
display: flex;
flex-direction: column;
gap: var(--space-4);
padding-top: var(--space-4);
padding-bottom: var(--space-3);
}
}
</style>
<div class="api-description">
<div class="gutter"></div>
<div class="content">
<MarkdownCustom {body} />
{"see" in macros && <ApiMacroSee value={macros.see} />}
</div>
</div>
@@ -1,8 +1,8 @@
--- ---
import type { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
import { api } from "../core/api/dynamic"; import { api } from "../core/api/dynamic";
import ApiDescription from "./ApiDescription.astro";
import { ApiTester } from "./ApiTester"; import { ApiTester } from "./ApiTester";
import { MarkdownCustom } from "./MarkdownCustom";
interface Props { interface Props {
locale: string; locale: string;
@@ -11,19 +11,17 @@ interface Props {
const { locale, api: apiData } = Astro.props; const { locale, api: apiData } = Astro.props;
const strings = await api.strings(locale); const strings = await api.strings(locale);
const hasSlugs = apiData.id.includes("["); const body = apiData.data.docs ?? strings.api.no_docs;
--- ---
<style> <style>
.container { .container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-4);
} }
</style> </style>
<div class="container"> <div class="container">
<ApiTester client:idle {locale} path={apiData.id} /> <ApiTester client:idle {locale} path={apiData.id} />
<ApiDescription {body} />
<MarkdownCustom body={apiData.data.docs ?? strings.api.no_docs} />
</div> </div>
@@ -0,0 +1,21 @@
---
import { Link } from "./Link";
import { Text } from "./Text";
interface Props {
value: string;
}
const bodyPattern = /^([a-z0-9-\/\.]+) (.+)$/;
const { value } = Astro.props;
const match = value.match(bodyPattern);
if (match === null) {
throw new Error(`Invalid value for ApiMacroSee: ${value}`);
}
const path = match[1];
const message = match[2];
---
<Text><Text color="tomato">See</Text> <Link>{path}</Link> {message}</Text>
@@ -1,4 +1,5 @@
import { useState } from "react"; import { PlayIcon } from "@radix-ui/react-icons";
import { Fragment, useState } from "react";
import { import {
LocaleProvider, LocaleProvider,
type LocaleAcceptorProps, type LocaleAcceptorProps,
@@ -6,8 +7,8 @@ import {
import { useStrings } from "../../hooks/useStrings"; import { useStrings } from "../../hooks/useStrings";
import { Button } from "../Button"; import { Button } from "../Button";
import { Code } from "../Code"; import { Code } from "../Code";
import { Heading } from "../Heading";
import { Link } from "../Link"; import { Link } from "../Link";
import { Text } from "../Text";
import { TextField } from "../TextField"; import { TextField } from "../TextField";
import styles from "./index.module.css"; import styles from "./index.module.css";
@@ -40,18 +41,17 @@ function Content({ path }: Props) {
return ( return (
<div className={styles.tester}> <div className={styles.tester}>
<Heading size="3"> <Text weight="medium">
<Code className={styles.title}> <Code className={styles.title}>
{path.split(slugPattern).map((text, index) => { {path.split(slugPattern).map((text, index) => {
const slug = slugs[index - 1]; const slug = slugs[index - 1];
return ( return (
<> <Fragment key={index}>
{index > 0 && ( {index > 0 && (
<TextField <TextField
className={styles.slug} className={styles.slug}
placeholder={`${slug}`} placeholder={`[${slug}]`}
monospace
align="center" align="center"
autoWidth autoWidth
onChange={(event) => { onChange={(event) => {
@@ -63,14 +63,16 @@ function Content({ path }: Props) {
/> />
)} )}
<span key={index}>{text}</span> <span key={index}>{text}</span>
</> </Fragment>
); );
})} })}
</Code> </Code>
</Heading> </Text>
<Link underline="never" href={href} target="_blank"> <Link underline="never" href={href} target="_blank">
<Button>{strings.api.test}</Button> <Button>
{strings.api.test} <PlayIcon />
</Button>
</Link> </Link>
</div> </div>
); );
@@ -11,7 +11,7 @@
box-shadow: var(--shadow-interactive), var(--shadow-cavity); box-shadow: var(--shadow-interactive), var(--shadow-cavity);
cursor: text; cursor: text;
font-size: var(--font-size-regular); font: inherit;
color: var(--gray-11); color: var(--gray-11);
&[data-has-icon="true"] { &[data-has-icon="true"] {
@@ -51,8 +51,7 @@
border: none; border: none;
cursor: inherit; cursor: inherit;
font-size: inherit; font: inherit;
font-weight: medium;
padding: var(--space-3) var(--space-4); padding: var(--space-3) var(--space-4);
color: var(--gray-12); color: var(--gray-12);
@@ -71,9 +70,5 @@
&[data-align="right"] { &[data-align="right"] {
text-align: right; text-align: right;
} }
&[data-monospace="true"] {
font-family: var(--font-family-mono);
}
} }
} }
@@ -13,7 +13,6 @@ import "./index.css";
export interface TextFieldProps extends ComponentProps<"input"> { export interface TextFieldProps extends ComponentProps<"input"> {
children?: ReactNode; children?: ReactNode;
align?: "left" | "center" | "right"; align?: "left" | "center" | "right";
monospace?: boolean;
autoWidth?: boolean; autoWidth?: boolean;
} }
@@ -22,7 +21,6 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
{ {
children, children,
className, className,
monospace,
autoWidth, autoWidth,
placeholder, placeholder,
align, align,
@@ -58,7 +56,6 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldProps>(
{children} {children}
<input <input
data-align={align === "left" ? undefined : align} data-align={align === "left" ? undefined : align}
data-monospace={monospace}
disabled={disabled} disabled={disabled}
ref={input} ref={input}
onChange={handleChange} onChange={handleChange}
@@ -10,9 +10,9 @@ export const getStaticPaths = (async () => {
}) satisfies GetStaticPaths; }) satisfies GetStaticPaths;
/** /**
* Returns data on an avatar based on its id. @see avatars/list.json for a list * Returns data on an avatar based on its `id`.
* of all avatar ids.
* *
* @see avatars/list.json for all avatar ids.
* @type avatar * @type avatar
*/ */
export async function GET({ params }: APIContext<never, { id: string }>) { export async function GET({ params }: APIContext<never, { id: string }>) {