import type { Children, Namekey, Refkey } from "@alloy-js/core";
import {
Block,
For,
MemberDeclaration,
Name,
Prose,
Show,
splitProps,
} from "@alloy-js/core";
import { useTSNamePolicy } from "../name-policy.js";
import {
createMemberSymbol,
createTypeAndValueSymbol,
} from "../symbols/index.js";
import { TSSymbolFlags } from "../symbols/ts-output-symbol.js";
import { getCallSignatureProps } from "../utils.js";
import type { CallSignatureProps } from "./CallSignature.jsx";
import { CallSignature } from "./CallSignature.jsx";
import type { CommonDeclarationProps } from "./Declaration.jsx";
import { Declaration } from "./Declaration.jsx";
import { JSDoc } from "./JSDoc.jsx";
import { JSDocParams } from "./JSDocParam.jsx";
import { LexicalScope } from "./LexicalScope.jsx";
import { MemberScope } from "./MemberScope.jsx";
import { PropertyName } from "./PropertyName.jsx";
import { TypeRefContext } from "./TypeRefContext.jsx";
export interface ClassDeclarationProps extends CommonDeclarationProps {
extends?: Children;
implements?: Children[];
}
/**
* Create a TypeScript class declaration.
*
* @remarks
*
* @example
*
* ```tsx
* const myPetRefkey = refkey();
* const Animal = refkey();
* const staticMember = refkey();
* const instanceMember = refkey();
*
*
*
* "hello"
*
*
*
*
* this.name = name;
*
*
*
*
* new {Animal}();
*
*
* {staticMember}; // Animal.something
* // myPet.name
* {memberRefkey(myPetRefkey, instanceMember)}
* ```
*/
export function ClassDeclaration(props: ClassDeclarationProps) {
const extendsPart = props.extends && <> extends {props.extends}>;
const implementsPart = props.implements && props.implements.length > 0 && (
<>
{" "}
implements{" "}
{(implement) => implement}
>
);
const sym = createTypeAndValueSymbol(props.name, {
refkeys: props.refkey,
export: props.export,
default: props.default,
metadata: props.metadata,
hasInstanceMembers: true,
namePolicy: useTSNamePolicy().for("class"),
});
return (
<>
class
{extendsPart}
{implementsPart} {props.children}
>
);
}
export interface ClassMemberProps {
name: string | Namekey;
refkey?: Refkey;
public?: boolean;
private?: boolean;
protected?: boolean;
jsPrivate?: boolean;
static?: boolean;
children?: Children;
doc?: Children;
nullish?: boolean;
}
export function ClassMember(props: ClassMemberProps) {
let tsFlags = TSSymbolFlags.None;
if (props.nullish) {
tsFlags |= TSSymbolFlags.Nullish;
}
const sym = createMemberSymbol(props.name, props, {
refkeys: props.refkey,
tsFlags,
namePolicy: useTSNamePolicy().for("class-member-data"),
});
return (
<>
{props.public && "public "}
{props.private && "private "}
{props.protected && "protected "}
{props.static && "static "}
{props.children}
>
);
}
export interface ClassFieldProps extends ClassMemberProps {
type?: Children;
optional?: boolean;
children?: Children;
}
export function ClassField(props: ClassFieldProps) {
const optionality = props.optional ? "?" : "";
const typeSection = props.type && (
<>
{optionality}: {props.type}
>
);
const initializerSection = props.children && <> = {props.children}>;
const nullish = props.nullish ?? props.optional;
return (
{typeSection}
{initializerSection}
);
}
export interface ClassMethodProps extends ClassMemberProps, CallSignatureProps {
async?: boolean;
children?: Children;
}
export function ClassMethod(props: ClassMethodProps) {
const callProps = getCallSignatureProps(props);
const [_, rest] = splitProps(props, ["doc"]);
return (
<>
{props.doc && }
{Array.isArray(rest.parameters) && (
)}
{props.async && "async "}
{props.children}
>
);
}