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} ); }