shelving 1.253.0 → 1.253.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extract/TypescriptExtractor.d.ts +2 -2
- package/extract/TypescriptExtractor.js +53 -73
- package/package.json +1 -1
- package/ui/block/Card.module.css +2 -1
- package/ui/docs/DocumentationDescription.d.ts +8 -5
- package/ui/docs/DocumentationDescription.js +12 -10
- package/ui/docs/DocumentationDescription.tsx +26 -12
- package/ui/docs/DocumentationPage.d.ts +5 -5
- package/ui/docs/DocumentationPage.js +8 -9
- package/ui/docs/DocumentationPage.test.tsx +36 -10
- package/ui/docs/DocumentationPage.tsx +9 -8
- package/ui/docs/DocumentationParams.js +8 -22
- package/ui/docs/DocumentationParams.tsx +15 -29
- package/ui/docs/DocumentationProperties.d.ts +26 -0
- package/ui/docs/DocumentationProperties.js +32 -0
- package/ui/docs/DocumentationProperties.tsx +83 -0
- package/ui/docs/DocumentationType.d.ts +33 -0
- package/ui/docs/DocumentationType.js +32 -0
- package/ui/docs/DocumentationType.tsx +48 -0
- package/ui/docs/index.d.ts +2 -0
- package/ui/docs/index.js +2 -0
- package/ui/docs/index.ts +2 -0
- package/ui/layout/CenteredLayout.js +2 -3
- package/ui/layout/CenteredLayout.md +1 -1
- package/ui/layout/CenteredLayout.module.css +61 -1
- package/ui/layout/CenteredLayout.tsx +2 -3
- package/ui/layout/Layout.d.ts +0 -7
- package/ui/layout/Layout.js +0 -9
- package/ui/layout/Layout.ts +0 -11
- package/ui/layout/SidebarLayout.js +2 -3
- package/ui/layout/SidebarLayout.md +1 -1
- package/ui/layout/SidebarLayout.module.css +44 -5
- package/ui/layout/SidebarLayout.tsx +2 -3
- package/ui/misc/StatusIcon.md +10 -1
- package/ui/misc/StatusIcon.module.css +4 -0
- package/ui/misc/Tag.module.css +1 -1
- package/util/tree.d.ts +4 -2
- package/ui/layout/Layout.module.css +0 -73
|
@@ -9,9 +9,9 @@ import { FileExtractor } from "./FileExtractor.js";
|
|
|
9
9
|
* - Class declarations synthesise their `signatures`, `params`, and `returns` from the constructor — `new ClassName<…>(…)` including generics, one signature per constructor overload, with `returns` set to the class type. Param descriptions come from the constructor's `@param` first, then the class's `@param`.
|
|
10
10
|
* - A `@kind` tag in a symbol's JSDoc overrides the inferred kind — e.g. `@kind component` relabels a React component (otherwise a `function`) so the docs site groups and colours it as a component. The override also drops the trailing `()` from the title, since a non-function kind reads as a bare name.
|
|
11
11
|
* - Sets `description` (a plain-text summary from the first JSDoc paragraph) on every `tree-documentation` child.
|
|
12
|
-
* - Sets `title` on every `tree-documentation` child — `name()` for functions, `Class.name()` for methods,
|
|
12
|
+
* - Sets `title` on every `tree-documentation` child — `name()` for functions, `Class.name()` for methods, bare `name` for other kinds. (Data members are not child elements — see `properties` below.)
|
|
13
13
|
* - Records relational metadata as raw strings for render-time linking: `class` (owning class), `readonly`, `extends` / `implements` (full heritage type text including generic arguments, e.g. `AbstractStore<string>` or `Omit<StringSchemaOptions, "value">`), and `types` (the type names a `type` alias's body references, e.g. `OtherType` in `string | OtherType`).
|
|
14
|
-
* - Records a structured `properties` list for interfaces and object-literal `type` aliases — each member's name, type, optionality,
|
|
14
|
+
* - Records a structured `properties` list for classes, interfaces, and object-literal `type` aliases — each data member's (property/getter/setter) name, type, optionality, default, and description. This is the single source for a type's data members: they render as the type's Properties table and flatten into an options-bag parameter's fields at render time, rather than each becoming its own child element. Methods stay as child elements.
|
|
15
15
|
* - Names a destructured (binding-pattern) parameter for the Param column — which has no name of its own — from an explicit `@param`, else its rest element (`...options`), else a type-derived fallback (`props` / `options`). The signature still shows the full `{ … }`.
|
|
16
16
|
* - Pretty-prints object-literal signatures (interfaces and object-literal `type` aliases) as multi-line `{ … }` blocks, one member per line; other type bodies (`string | null`, mapped types, …) are emitted verbatim.
|
|
17
17
|
* - Members declared with the `override` or `declare` modifier are skipped — the base class already documents overrides, and `declare` members are ambient type-only re-declarations rather than new API.
|
|
@@ -10,9 +10,9 @@ import { extractMarkdownProps } from "./MarkupExtractor.js";
|
|
|
10
10
|
* - Class declarations synthesise their `signatures`, `params`, and `returns` from the constructor — `new ClassName<…>(…)` including generics, one signature per constructor overload, with `returns` set to the class type. Param descriptions come from the constructor's `@param` first, then the class's `@param`.
|
|
11
11
|
* - A `@kind` tag in a symbol's JSDoc overrides the inferred kind — e.g. `@kind component` relabels a React component (otherwise a `function`) so the docs site groups and colours it as a component. The override also drops the trailing `()` from the title, since a non-function kind reads as a bare name.
|
|
12
12
|
* - Sets `description` (a plain-text summary from the first JSDoc paragraph) on every `tree-documentation` child.
|
|
13
|
-
* - Sets `title` on every `tree-documentation` child — `name()` for functions, `Class.name()` for methods,
|
|
13
|
+
* - Sets `title` on every `tree-documentation` child — `name()` for functions, `Class.name()` for methods, bare `name` for other kinds. (Data members are not child elements — see `properties` below.)
|
|
14
14
|
* - Records relational metadata as raw strings for render-time linking: `class` (owning class), `readonly`, `extends` / `implements` (full heritage type text including generic arguments, e.g. `AbstractStore<string>` or `Omit<StringSchemaOptions, "value">`), and `types` (the type names a `type` alias's body references, e.g. `OtherType` in `string | OtherType`).
|
|
15
|
-
* - Records a structured `properties` list for interfaces and object-literal `type` aliases — each member's name, type, optionality,
|
|
15
|
+
* - Records a structured `properties` list for classes, interfaces, and object-literal `type` aliases — each data member's (property/getter/setter) name, type, optionality, default, and description. This is the single source for a type's data members: they render as the type's Properties table and flatten into an options-bag parameter's fields at render time, rather than each becoming its own child element. Methods stay as child elements.
|
|
16
16
|
* - Names a destructured (binding-pattern) parameter for the Param column — which has no name of its own — from an explicit `@param`, else its rest element (`...options`), else a type-derived fallback (`props` / `options`). The signature still shows the full `{ … }`.
|
|
17
17
|
* - Pretty-prints object-literal signatures (interfaces and object-literal `type` aliases) as multi-line `{ … }` blocks, one member per line; other type bodies (`string | null`, mapped types, …) are emitted verbatim.
|
|
18
18
|
* - Members declared with the `override` or `declare` modifier are skipped — the base class already documents overrides, and `declare` members are ambient type-only re-declarations rather than new API.
|
|
@@ -199,12 +199,14 @@ function _getReferencedTypes(statement, source) {
|
|
|
199
199
|
return names.length ? names : undefined;
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
|
-
* Extract structured property entries from
|
|
203
|
-
* -
|
|
204
|
-
* -
|
|
202
|
+
* Extract structured property entries from a class, interface, or object-literal `type` alias, mirroring the `DocumentationParam` shape.
|
|
203
|
+
* - This is the single source of truth for a type's data members: properties (and getters/setters) are documented here as a structured list, not as their own child elements. Methods stay as child elements (see `_getClassMembers`).
|
|
204
|
+
* - Used both to render the type's own Properties table and to flatten an options-bag parameter into its individual fields at render time (resolve the param's type in the tree map, then list these).
|
|
205
|
+
* - Skips private/protected, `_`-prefixed, `override`, and `declare` members. Optionality comes from a `?` token; defaults from a class-field initializer or a member's `@default` JSDoc; descriptions from each member's own JSDoc.
|
|
206
|
+
* - Getters/setters fold into a single entry per name (the getter's type wins for a get/set pair).
|
|
205
207
|
*/
|
|
206
208
|
function _getProperties(statement, source) {
|
|
207
|
-
const members = ts.isInterfaceDeclaration(statement)
|
|
209
|
+
const members = ts.isInterfaceDeclaration(statement) || ts.isClassDeclaration(statement)
|
|
208
210
|
? statement.members
|
|
209
211
|
: ts.isTypeAliasDeclaration(statement) && ts.isTypeLiteralNode(statement.type)
|
|
210
212
|
? statement.type.members
|
|
@@ -213,19 +215,48 @@ function _getProperties(statement, source) {
|
|
|
213
215
|
return;
|
|
214
216
|
const properties = [];
|
|
215
217
|
for (const member of members) {
|
|
216
|
-
if (!ts.isPropertySignature(member))
|
|
217
|
-
continue;
|
|
218
218
|
const name = member.name && ts.isIdentifier(member.name) ? member.name.text : undefined;
|
|
219
219
|
if (!name || name.startsWith("_"))
|
|
220
220
|
continue;
|
|
221
|
+
const modifiers = ts.canHaveModifiers(member) ? ts.getModifiers(member) : undefined;
|
|
222
|
+
// Skip private/protected (not public API), `override` (documented on the base class), and `declare` (ambient re-declarations).
|
|
223
|
+
if (modifiers?.some(m => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword))
|
|
224
|
+
continue;
|
|
225
|
+
if (modifiers?.some(m => m.kind === ts.SyntaxKind.OverrideKeyword || m.kind === ts.SyntaxKind.DeclareKeyword))
|
|
226
|
+
continue;
|
|
221
227
|
const jsDoc = _getJSDoc(member, source);
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
228
|
+
if (ts.isPropertySignature(member) || ts.isPropertyDeclaration(member)) {
|
|
229
|
+
// A class field's initializer is its default; otherwise fall back to an explicit `@default` tag.
|
|
230
|
+
const def = (ts.isPropertyDeclaration(member) ? member.initializer?.getText(source) : undefined) ?? jsDoc?.default;
|
|
231
|
+
properties.push({
|
|
232
|
+
name,
|
|
233
|
+
type: member.type?.getText(source),
|
|
234
|
+
description: jsDoc?.description,
|
|
235
|
+
optional: !!member.questionToken,
|
|
236
|
+
default: def,
|
|
237
|
+
readonly: modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) || undefined,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
else if (ts.isGetAccessor(member) || ts.isSetAccessor(member)) {
|
|
241
|
+
const type = ts.isGetAccessor(member) ? member.type?.getText(source) : member.parameters[0]?.type?.getText(source);
|
|
242
|
+
const index = properties.findIndex(p => p.name === name);
|
|
243
|
+
const found = index >= 0 ? properties[index] : undefined;
|
|
244
|
+
// Fold a get/set pair into one entry: the getter's declared type wins, and the matching setter clears read-only.
|
|
245
|
+
if (found) {
|
|
246
|
+
properties[index] = { ...found, type: ts.isGetAccessor(member) && type ? type : found.type, readonly: undefined };
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
// A lone getter is read-only until a setter is seen; a lone setter is writable.
|
|
250
|
+
properties.push({
|
|
251
|
+
name,
|
|
252
|
+
type,
|
|
253
|
+
description: jsDoc?.description,
|
|
254
|
+
optional: false,
|
|
255
|
+
default: jsDoc?.default,
|
|
256
|
+
readonly: ts.isGetAccessor(member) || undefined,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
229
260
|
}
|
|
230
261
|
return properties.length ? properties : undefined;
|
|
231
262
|
}
|
|
@@ -434,12 +465,12 @@ function _getReturns(statement, source, jsDocReturns, name) {
|
|
|
434
465
|
return [{ type }];
|
|
435
466
|
}
|
|
436
467
|
/**
|
|
437
|
-
* Extract class or interface
|
|
438
|
-
* -
|
|
468
|
+
* Extract a class or interface's **methods** as child elements.
|
|
469
|
+
* - Data members (properties, getters/setters) are NOT child elements — they're collected as a structured list by [`_getProperties`](#) and rendered as the type's Properties table instead. Only methods, which carry their own params/returns/throws docs, warrant a dedicated page.
|
|
470
|
+
* - `className` is stamped onto every method as its `class` prop (the source of the qualified flat key and the "member of …" affordance) and is prebaked into the member `title` (`Class.name()`).
|
|
439
471
|
* - Members declared with the `override` modifier are skipped — the base class already documents them, so a subclass page lists only its newly-introduced API.
|
|
440
|
-
* - Members declared with the `declare` modifier are skipped — they're ambient type-only re-declarations
|
|
441
|
-
* -
|
|
442
|
-
* - `static` members are labelled `static method` / `static property` so the docs site groups them in their own sections, separate from instance `method` / `property`, and their rendered signature is prefixed with the `static ` keyword.
|
|
472
|
+
* - Members declared with the `declare` modifier are skipped — they're ambient type-only re-declarations, not new API.
|
|
473
|
+
* - `static` methods are labelled `static method` so the docs site groups them in their own section, separate from instance `method`s, and their rendered signature is prefixed with the `static ` keyword.
|
|
443
474
|
*/
|
|
444
475
|
function _getClassMembers(statement, source, className) {
|
|
445
476
|
if (!ts.isClassDeclaration(statement) && !ts.isInterfaceDeclaration(statement))
|
|
@@ -459,7 +490,7 @@ function _getClassMembers(statement, source, className) {
|
|
|
459
490
|
// Skip `declare` members — ambient type-only re-declarations (e.g. a subclass narrowing an inherited property's type), not new API.
|
|
460
491
|
if (modifiers?.some(m => m.kind === ts.SyntaxKind.DeclareKeyword))
|
|
461
492
|
continue;
|
|
462
|
-
// `static`
|
|
493
|
+
// `static` methods are grouped and labelled separately from instance methods (`static method`),
|
|
463
494
|
// and carry the `static ` keyword in their rendered signature.
|
|
464
495
|
const isStatic = modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword);
|
|
465
496
|
const staticPrefix = isStatic ? "static " : "";
|
|
@@ -495,58 +526,7 @@ function _getClassMembers(statement, source, className) {
|
|
|
495
526
|
});
|
|
496
527
|
}
|
|
497
528
|
}
|
|
498
|
-
|
|
499
|
-
const type = member.type?.getText(source);
|
|
500
|
-
const readonly = modifiers?.some(m => m.kind === ts.SyntaxKind.ReadonlyKeyword) || undefined;
|
|
501
|
-
members.push({
|
|
502
|
-
type: "tree-documentation",
|
|
503
|
-
key: name,
|
|
504
|
-
props: {
|
|
505
|
-
name,
|
|
506
|
-
title: `${className}.${name}`,
|
|
507
|
-
description,
|
|
508
|
-
content,
|
|
509
|
-
kind: isStatic ? "static property" : "property",
|
|
510
|
-
class: className,
|
|
511
|
-
readonly,
|
|
512
|
-
signatures: type ? [`${staticPrefix}${readonly ? "readonly " : ""}${name}: ${type}`] : undefined,
|
|
513
|
-
},
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
else if (ts.isGetAccessor(member) || ts.isSetAccessor(member)) {
|
|
517
|
-
// Getters/setters fold into one `property`. A getter alone (no setter) is read-only; a setter clears that.
|
|
518
|
-
const type = ts.isGetAccessor(member) ? member.type?.getText(source) : member.parameters[0]?.type?.getText(source);
|
|
519
|
-
const key = name;
|
|
520
|
-
const existingIndex = members.findIndex(m => m.key === key);
|
|
521
|
-
const existing = members[existingIndex];
|
|
522
|
-
if (existing) {
|
|
523
|
-
members[existingIndex] = {
|
|
524
|
-
...existing,
|
|
525
|
-
props: {
|
|
526
|
-
...existing.props,
|
|
527
|
-
// A getter + setter pair is writable — drop the read-only flag and the `readonly ` signature prefix.
|
|
528
|
-
readonly: undefined,
|
|
529
|
-
signatures: type ? [`${staticPrefix}${name}: ${type}`] : existing.props.signatures,
|
|
530
|
-
},
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
members.push({
|
|
535
|
-
type: "tree-documentation",
|
|
536
|
-
key,
|
|
537
|
-
props: {
|
|
538
|
-
name,
|
|
539
|
-
title: `${className}.${name}`,
|
|
540
|
-
description,
|
|
541
|
-
content,
|
|
542
|
-
kind: isStatic ? "static property" : "property",
|
|
543
|
-
class: className,
|
|
544
|
-
readonly: ts.isGetAccessor(member) || undefined,
|
|
545
|
-
signatures: type ? [`${staticPrefix}${ts.isGetAccessor(member) ? "readonly " : ""}${name}: ${type}`] : undefined,
|
|
546
|
-
},
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
}
|
|
529
|
+
// Properties, getters, and setters are not child elements — `_getProperties` collects them as a structured list instead.
|
|
550
530
|
}
|
|
551
531
|
return members.length ? members : undefined;
|
|
552
532
|
}
|
package/package.json
CHANGED
package/ui/block/Card.module.css
CHANGED
|
@@ -68,7 +68,8 @@
|
|
|
68
68
|
|
|
69
69
|
@layer overrides {
|
|
70
70
|
.card {
|
|
71
|
-
|
|
71
|
+
/* Show the focus ring only while the navigable overlay is keyboard-focused; hide it otherwise (including non-clickable cards, which have no overlay). */
|
|
72
|
+
&:not(:has(.overlay:focus-visible)) {
|
|
72
73
|
outline-color: transparent;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -11,16 +11,19 @@ export interface DocumentationDescriptionProps {
|
|
|
11
11
|
readonly default?: string | undefined;
|
|
12
12
|
/** Whether the value is optional — pass an explicit boolean to opt into the note: `false` appends `Required.` (when there's no default), `true` appends nothing. Leave `undefined` to suppress the note entirely (e.g. for returns/throws). */
|
|
13
13
|
readonly optional?: boolean | undefined;
|
|
14
|
+
/** Whether the value is read-only — appends a trailing `Readonly` note at the very end (after any `Defaults to …` / `Required.`). */
|
|
15
|
+
readonly readonly?: boolean | undefined;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Render a documentation table row's description cell.
|
|
17
|
-
* - The description is parsed as inline markup (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source.
|
|
18
|
-
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders `
|
|
19
|
+
* - The description is parsed as inline markup via `TreeMarkup` (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source — and each inline-code span auto-links to its documented token when one exists.
|
|
20
|
+
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders a `required` `<Tag>`. (Optionality has no tag — it's implicit, and an optional value usually carries the longer `Defaults to …` text instead.)
|
|
21
|
+
* - When `readonly` is set, a `readonly` `<Tag>` is appended at the very end (after any default/required note).
|
|
19
22
|
* - Wrapped in `<Prose>` so markup-produced `<code>` (and other inline) elements pick up the standard prose typography (the chip background, etc.) — a bare `<code>` is only styled inside a `.prose` ancestor.
|
|
20
23
|
*
|
|
21
24
|
* @kind component
|
|
22
|
-
* @returns The description and any trailing
|
|
23
|
-
* @example <DocumentationDescription description="The `foo` value." optional={false} />
|
|
25
|
+
* @returns The description and any trailing notes wrapped in a `<Prose>`, or `null` when all are empty.
|
|
26
|
+
* @example <DocumentationDescription description="The `foo` value." optional={false} readonly />
|
|
24
27
|
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationDescription/DocumentationDescription
|
|
25
28
|
*/
|
|
26
|
-
export declare function DocumentationDescription({ description, default: def, optional }: DocumentationDescriptionProps): ReactNode;
|
|
29
|
+
export declare function DocumentationDescription({ description, default: def, optional, readonly }: DocumentationDescriptionProps): ReactNode;
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Prose } from "../block/Prose.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Tag } from "../misc/Tag.js";
|
|
4
4
|
import { TreeLink } from "../tree/TreeLink.js";
|
|
5
|
+
import { TreeMarkup } from "../tree/TreeMarkup.js";
|
|
5
6
|
/**
|
|
6
7
|
* Render a documentation table row's description cell.
|
|
7
|
-
* - The description is parsed as inline markup (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source.
|
|
8
|
-
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders `
|
|
8
|
+
* - The description is parsed as inline markup via `TreeMarkup` (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source — and each inline-code span auto-links to its documented token when one exists.
|
|
9
|
+
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders a `required` `<Tag>`. (Optionality has no tag — it's implicit, and an optional value usually carries the longer `Defaults to …` text instead.)
|
|
10
|
+
* - When `readonly` is set, a `readonly` `<Tag>` is appended at the very end (after any default/required note).
|
|
9
11
|
* - Wrapped in `<Prose>` so markup-produced `<code>` (and other inline) elements pick up the standard prose typography (the chip background, etc.) — a bare `<code>` is only styled inside a `.prose` ancestor.
|
|
10
12
|
*
|
|
11
13
|
* @kind component
|
|
12
|
-
* @returns The description and any trailing
|
|
13
|
-
* @example <DocumentationDescription description="The `foo` value." optional={false} />
|
|
14
|
+
* @returns The description and any trailing notes wrapped in a `<Prose>`, or `null` when all are empty.
|
|
15
|
+
* @example <DocumentationDescription description="The `foo` value." optional={false} readonly />
|
|
14
16
|
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationDescription/DocumentationDescription
|
|
15
17
|
*/
|
|
16
|
-
export function DocumentationDescription({ description, default: def, optional }) {
|
|
17
|
-
const body = description ? _jsx(
|
|
18
|
-
const
|
|
19
|
-
if (!body && !
|
|
18
|
+
export function DocumentationDescription({ description, default: def, optional, readonly }) {
|
|
19
|
+
const body = description ? _jsx(TreeMarkup, { context: "inline", children: description }) : null;
|
|
20
|
+
const requirement = def ? (_jsxs(_Fragment, { children: ["Defaults to ", _jsx(TreeLink, { name: def })] })) : optional === false ? (_jsx(Tag, { children: "required" })) : null;
|
|
21
|
+
if (!body && !requirement && !readonly)
|
|
20
22
|
return null;
|
|
21
|
-
return (_jsxs(Prose, { children: [body, body
|
|
23
|
+
return (_jsxs(Prose, { children: [body, requirement ? (_jsxs(_Fragment, { children: [body ? " " : null, requirement] })) : null, readonly ? (_jsxs(_Fragment, { children: [body || requirement ? " " : null, _jsx(Tag, { children: "readonly" })] })) : null] }));
|
|
22
24
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import { Prose } from "../block/Prose.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Tag } from "../misc/Tag.js";
|
|
4
4
|
import { TreeLink } from "../tree/TreeLink.js";
|
|
5
|
+
import { TreeMarkup } from "../tree/TreeMarkup.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Props for `DocumentationDescription` — a description cell's resolved text, plus an optional default/optionality note.
|
|
@@ -15,34 +16,47 @@ export interface DocumentationDescriptionProps {
|
|
|
15
16
|
readonly default?: string | undefined;
|
|
16
17
|
/** Whether the value is optional — pass an explicit boolean to opt into the note: `false` appends `Required.` (when there's no default), `true` appends nothing. Leave `undefined` to suppress the note entirely (e.g. for returns/throws). */
|
|
17
18
|
readonly optional?: boolean | undefined;
|
|
19
|
+
/** Whether the value is read-only — appends a trailing `Readonly` note at the very end (after any `Defaults to …` / `Required.`). */
|
|
20
|
+
readonly readonly?: boolean | undefined;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* Render a documentation table row's description cell.
|
|
22
|
-
* - The description is parsed as inline markup (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source.
|
|
23
|
-
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders `
|
|
25
|
+
* - The description is parsed as inline markup via `TreeMarkup` (`context="inline"`), so backticks, emphasis and links resolve rather than showing as literal source — and each inline-code span auto-links to its documented token when one exists.
|
|
26
|
+
* - When a `default` is given it renders a trailing `Defaults to …` note on the same line (linking the value when it's a documented token); otherwise, when `optional` is explicitly `false`, it renders a `required` `<Tag>`. (Optionality has no tag — it's implicit, and an optional value usually carries the longer `Defaults to …` text instead.)
|
|
27
|
+
* - When `readonly` is set, a `readonly` `<Tag>` is appended at the very end (after any default/required note).
|
|
24
28
|
* - Wrapped in `<Prose>` so markup-produced `<code>` (and other inline) elements pick up the standard prose typography (the chip background, etc.) — a bare `<code>` is only styled inside a `.prose` ancestor.
|
|
25
29
|
*
|
|
26
30
|
* @kind component
|
|
27
|
-
* @returns The description and any trailing
|
|
28
|
-
* @example <DocumentationDescription description="The `foo` value." optional={false} />
|
|
31
|
+
* @returns The description and any trailing notes wrapped in a `<Prose>`, or `null` when all are empty.
|
|
32
|
+
* @example <DocumentationDescription description="The `foo` value." optional={false} readonly />
|
|
29
33
|
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationDescription/DocumentationDescription
|
|
30
34
|
*/
|
|
31
|
-
export function DocumentationDescription({ description, default: def, optional }: DocumentationDescriptionProps): ReactNode {
|
|
32
|
-
const body = description ? <
|
|
33
|
-
const
|
|
35
|
+
export function DocumentationDescription({ description, default: def, optional, readonly }: DocumentationDescriptionProps): ReactNode {
|
|
36
|
+
const body = description ? <TreeMarkup context="inline">{description}</TreeMarkup> : null;
|
|
37
|
+
const requirement = def ? (
|
|
34
38
|
<>
|
|
35
39
|
Defaults to <TreeLink name={def} />
|
|
36
40
|
</>
|
|
37
41
|
) : optional === false ? (
|
|
38
|
-
|
|
42
|
+
<Tag>required</Tag>
|
|
39
43
|
) : null;
|
|
40
|
-
if (!body && !
|
|
44
|
+
if (!body && !requirement && !readonly) return null;
|
|
41
45
|
return (
|
|
42
46
|
<Prose>
|
|
43
47
|
{body}
|
|
44
|
-
{
|
|
45
|
-
|
|
48
|
+
{requirement ? (
|
|
49
|
+
<>
|
|
50
|
+
{body ? " " : null}
|
|
51
|
+
{requirement}
|
|
52
|
+
</>
|
|
53
|
+
) : null}
|
|
54
|
+
{readonly ? (
|
|
55
|
+
<>
|
|
56
|
+
{body || requirement ? " " : null}
|
|
57
|
+
<Tag>readonly</Tag>
|
|
58
|
+
</>
|
|
59
|
+
) : null}
|
|
46
60
|
</Prose>
|
|
47
61
|
);
|
|
48
62
|
}
|
|
@@ -2,11 +2,11 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { DocumentationElementProps } from "../../util/tree.js";
|
|
3
3
|
/**
|
|
4
4
|
* Page renderer for a `tree-documentation` element — the full detail page for a documented symbol.
|
|
5
|
-
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, referenced types, and examples.
|
|
6
|
-
* - In the Parameters / Returns / Throws tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A
|
|
7
|
-
* -
|
|
5
|
+
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, properties, referenced types, and examples.
|
|
6
|
+
* - In the Parameters / Returns / Throws / Properties tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A default renders as a `Defaults to …` note (linking the value when it's a documented token) rather than in a dedicated column.
|
|
7
|
+
* - A class/interface/object-literal type's data members render as the Properties table (see `DocumentationProperties`); an options-bag parameter whose type resolves to one is flattened into indented child rows from the same structured list.
|
|
8
8
|
* - A `type` alias's referenced type names render as a linked `Type` table, each row carrying the resolved element's `description` (exact-match only).
|
|
9
|
-
* - Child symbols are grouped by `kind` into card sections
|
|
9
|
+
* - Child symbols (functions, classes, methods — not data members) are grouped by `kind` into card sections, each under its own heading.
|
|
10
10
|
* - All sections are conditional — only render when they have entries.
|
|
11
11
|
*
|
|
12
12
|
* @kind component
|
|
@@ -14,4 +14,4 @@ import type { DocumentationElementProps } from "../../util/tree.js";
|
|
|
14
14
|
* @example <DocumentationPage {...element.props} />
|
|
15
15
|
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationPage/DocumentationPage
|
|
16
16
|
*/
|
|
17
|
-
export declare function DocumentationPage({ title, name, kind, description, content, signatures, params, returns, throws, types, examples, children, ...props }: DocumentationElementProps): ReactNode;
|
|
17
|
+
export declare function DocumentationPage({ title, name, kind, description, content, signatures, params, returns, throws, properties, types, examples, children, ...props }: DocumentationElementProps): ReactNode;
|
|
@@ -15,11 +15,12 @@ import { TreeMarkup } from "../tree/TreeMarkup.js";
|
|
|
15
15
|
import { DocumentationButtons } from "./DocumentationButtons.js";
|
|
16
16
|
import { DocumentationKind, getDocumentationKindColor } from "./DocumentationKind.js";
|
|
17
17
|
import { DocumentationParams } from "./DocumentationParams.js";
|
|
18
|
+
import { DocumentationProperties } from "./DocumentationProperties.js";
|
|
18
19
|
import { DocumentationReferences } from "./DocumentationReferences.js";
|
|
19
20
|
import { DocumentationReturns } from "./DocumentationReturns.js";
|
|
20
21
|
import { DocumentationSignatures } from "./DocumentationSignatures.js";
|
|
21
22
|
import { DocumentationThrows } from "./DocumentationThrows.js";
|
|
22
|
-
/** Documentation `kind`s grouped into card sections, in display order — pluralised, sentence-case headings. */
|
|
23
|
+
/** Documentation `kind`s grouped into card sections, in display order — pluralised, sentence-case headings. Data members (properties) are not child elements — they render as the Properties table instead. */
|
|
23
24
|
const KIND_SECTIONS = {
|
|
24
25
|
component: "Components",
|
|
25
26
|
function: "Functions",
|
|
@@ -28,9 +29,7 @@ const KIND_SECTIONS = {
|
|
|
28
29
|
type: "Types",
|
|
29
30
|
constant: "Constants",
|
|
30
31
|
"static method": "Static methods",
|
|
31
|
-
"static property": "Static properties",
|
|
32
32
|
method: "Methods",
|
|
33
|
-
property: "Properties",
|
|
34
33
|
};
|
|
35
34
|
/** Render a list of tree elements grouped into kind-based card sections, in `KIND_SECTIONS` order. */
|
|
36
35
|
function _renderSections(elements) {
|
|
@@ -57,11 +56,11 @@ function DocumentationChildren({ elements }) {
|
|
|
57
56
|
}
|
|
58
57
|
/**
|
|
59
58
|
* Page renderer for a `tree-documentation` element — the full detail page for a documented symbol.
|
|
60
|
-
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, referenced types, and examples.
|
|
61
|
-
* - In the Parameters / Returns / Throws tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A
|
|
62
|
-
* -
|
|
59
|
+
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, properties, referenced types, and examples.
|
|
60
|
+
* - In the Parameters / Returns / Throws / Properties tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A default renders as a `Defaults to …` note (linking the value when it's a documented token) rather than in a dedicated column.
|
|
61
|
+
* - A class/interface/object-literal type's data members render as the Properties table (see `DocumentationProperties`); an options-bag parameter whose type resolves to one is flattened into indented child rows from the same structured list.
|
|
63
62
|
* - A `type` alias's referenced type names render as a linked `Type` table, each row carrying the resolved element's `description` (exact-match only).
|
|
64
|
-
* - Child symbols are grouped by `kind` into card sections
|
|
63
|
+
* - Child symbols (functions, classes, methods — not data members) are grouped by `kind` into card sections, each under its own heading.
|
|
65
64
|
* - All sections are conditional — only render when they have entries.
|
|
66
65
|
*
|
|
67
66
|
* @kind component
|
|
@@ -69,6 +68,6 @@ function DocumentationChildren({ elements }) {
|
|
|
69
68
|
* @example <DocumentationPage {...element.props} />
|
|
70
69
|
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationPage/DocumentationPage
|
|
71
70
|
*/
|
|
72
|
-
export function DocumentationPage({ title, name, kind = "unknown", description, content, signatures, params, returns, throws, types, examples, children, ...props }) {
|
|
73
|
-
return (_jsx(Page, { title: title ?? name, description: description, children: _jsxs(Block, { color: getDocumentationKindColor(kind), children: [_jsx(Panel, { children: _jsxs(Header, { children: [_jsx(TreeBreadcrumbs, {}), _jsx(Title, { children: _jsxs(Row, { left: true, wrap: true, children: [title ?? name, kind && _jsx(DocumentationKind, { kind: kind, size: "normal" })] }) }), _jsx(DocumentationButtons, { ...props })] }) }), signatures?.length || params?.length || returns?.length || throws?.length || types?.length ? (_jsxs(Section, { children: [_jsx(DocumentationSignatures, { signatures: signatures }), _jsx(DocumentationParams, { params: params }), _jsx(DocumentationReturns, { returns: returns }), _jsx(DocumentationThrows, { throws: throws }), _jsx(DocumentationReferences, { types: types })] })) : null, content && (_jsx(Section, { children: _jsx(Prose, { children: _jsx(TreeMarkup, { children: content }) }) })), examples?.length && (_jsxs(Section, { children: [_jsx(Heading, { children: "Examples" }), examples.map(({ description }) => (_jsx(Preformatted, { children: description }, description)))] })), _jsx(DocumentationChildren, { elements: children })] }) }));
|
|
71
|
+
export function DocumentationPage({ title, name, kind = "unknown", description, content, signatures, params, returns, throws, properties, types, examples, children, ...props }) {
|
|
72
|
+
return (_jsx(Page, { title: title ?? name, description: description, children: _jsxs(Block, { color: getDocumentationKindColor(kind), children: [_jsx(Panel, { children: _jsxs(Header, { children: [_jsx(TreeBreadcrumbs, {}), _jsx(Title, { children: _jsxs(Row, { left: true, wrap: true, children: [title ?? name, kind && _jsx(DocumentationKind, { kind: kind, size: "normal" })] }) }), _jsx(DocumentationButtons, { ...props })] }) }), signatures?.length || params?.length || returns?.length || throws?.length || properties?.length || types?.length ? (_jsxs(Section, { children: [_jsx(DocumentationSignatures, { signatures: signatures }), _jsx(DocumentationParams, { params: params }), _jsx(DocumentationReturns, { returns: returns }), _jsx(DocumentationThrows, { throws: throws }), _jsx(DocumentationProperties, { properties: properties }), _jsx(DocumentationReferences, { types: types })] })) : null, content && (_jsx(Section, { children: _jsx(Prose, { children: _jsx(TreeMarkup, { children: content }) }) })), examples?.length && (_jsxs(Section, { children: [_jsx(Heading, { children: "Examples" }), examples.map(({ description }) => (_jsx(Preformatted, { children: description }, description)))] })), _jsx(DocumentationChildren, { elements: children })] }) }));
|
|
74
73
|
}
|
|
@@ -32,16 +32,45 @@ describe("DocumentationPage", () => {
|
|
|
32
32
|
test("renders a section only for kinds that have children", () => {
|
|
33
33
|
const html = render(
|
|
34
34
|
<DocumentationPage path="/Store" name="Store" kind="class">
|
|
35
|
-
{[doc("get", "method")
|
|
35
|
+
{[doc("get", "method")]}
|
|
36
36
|
</DocumentationPage>,
|
|
37
37
|
"./Store",
|
|
38
38
|
);
|
|
39
39
|
expect(html).toContain("Methods");
|
|
40
|
-
expect(html).toContain("Properties");
|
|
41
40
|
expect(html).not.toContain("Functions");
|
|
42
41
|
expect(html).not.toContain("Interfaces");
|
|
43
42
|
});
|
|
44
43
|
|
|
44
|
+
test("renders properties as a table with dot-prefixed names, dropping `| undefined` as optional", () => {
|
|
45
|
+
const html = render(
|
|
46
|
+
<DocumentationPage
|
|
47
|
+
path="/Opts"
|
|
48
|
+
name="Opts"
|
|
49
|
+
kind="interface"
|
|
50
|
+
properties={[
|
|
51
|
+
{ name: "caller", type: "AnyCaller | undefined", description: "The caller." },
|
|
52
|
+
{ name: "id", type: "string", description: "The id." },
|
|
53
|
+
{ name: "timeout", type: "number", description: "The timeout.", default: "20000" },
|
|
54
|
+
{ name: "size", type: "number", description: "The size.", readonly: true },
|
|
55
|
+
]}
|
|
56
|
+
/>,
|
|
57
|
+
"./Opts",
|
|
58
|
+
);
|
|
59
|
+
// Dedicated Properties table with dot-prefixed names.
|
|
60
|
+
expect(html).toContain(">Property</th>");
|
|
61
|
+
expect(html).toContain(">.caller</code>");
|
|
62
|
+
expect(html).toContain(">.timeout</code>");
|
|
63
|
+
// `| undefined` is dropped from the type and marks the property optional (no `Required.`).
|
|
64
|
+
expect(html).toContain(">AnyCaller</code>");
|
|
65
|
+
expect(html).not.toContain(">undefined</code>");
|
|
66
|
+
// A property with no default and no optionality gets a `required` tag; one with a default surfaces `Defaults to …`.
|
|
67
|
+
expect(html).toContain(">required</span>");
|
|
68
|
+
expect(html).toContain("Defaults to");
|
|
69
|
+
expect(html).toContain("20000");
|
|
70
|
+
// A read-only property appends a `readonly` tag at the end of its description.
|
|
71
|
+
expect(html).toContain(">readonly</span>");
|
|
72
|
+
});
|
|
73
|
+
|
|
45
74
|
test("renders parameters as a table, folding any default into the description as a `Defaults to …` line", () => {
|
|
46
75
|
const html = render(
|
|
47
76
|
<DocumentationPage
|
|
@@ -60,10 +89,10 @@ describe("DocumentationPage", () => {
|
|
|
60
89
|
expect(html).toContain(">Param</th>");
|
|
61
90
|
expect(html).toContain(">Type</th>");
|
|
62
91
|
expect(html).not.toContain(">Default</th>");
|
|
63
|
-
// A param with a default surfaces it as a `Defaults to …` note in its description; a param with neither a default nor optionality
|
|
92
|
+
// A param with a default surfaces it as a `Defaults to …` note in its description; a param with neither a default nor optionality gets a `required` tag.
|
|
64
93
|
expect(html).toContain("Defaults to");
|
|
65
94
|
expect(html).toContain("false");
|
|
66
|
-
expect(html).toContain("
|
|
95
|
+
expect(html).toContain(">required</span>");
|
|
67
96
|
// Returns table headers.
|
|
68
97
|
expect(html).toContain(">Return</th>");
|
|
69
98
|
expect(html).toContain("The new thing.");
|
|
@@ -110,19 +139,16 @@ describe("DocumentationPage", () => {
|
|
|
110
139
|
expect(html).not.toContain("`code`");
|
|
111
140
|
});
|
|
112
141
|
|
|
113
|
-
test("groups static
|
|
142
|
+
test("groups static methods into their own section, before instance methods", () => {
|
|
114
143
|
const html = render(
|
|
115
144
|
<DocumentationPage path="/Color" name="Color" kind="class">
|
|
116
|
-
{[doc("from", "static method"), doc("
|
|
145
|
+
{[doc("from", "static method"), doc("toString", "method")]}
|
|
117
146
|
</DocumentationPage>,
|
|
118
147
|
"./Color",
|
|
119
148
|
);
|
|
120
149
|
expect(html).toContain("Static methods");
|
|
121
|
-
expect(html).toContain("Static properties");
|
|
122
150
|
expect(html).toContain("Methods");
|
|
123
|
-
|
|
124
|
-
// Static sections render before their instance counterparts (the `Methods` / `Properties` headings use a capital, so they don't match inside `Static methods`).
|
|
151
|
+
// Static methods render before instance methods (the `Methods` heading uses a capital, so it doesn't match inside `Static methods`).
|
|
125
152
|
expect(html.indexOf("Static methods")).toBeLessThan(html.indexOf("Methods"));
|
|
126
|
-
expect(html.indexOf("Static properties")).toBeLessThan(html.indexOf("Properties"));
|
|
127
153
|
});
|
|
128
154
|
});
|
|
@@ -16,12 +16,13 @@ import { TreeMarkup } from "../tree/TreeMarkup.js";
|
|
|
16
16
|
import { DocumentationButtons } from "./DocumentationButtons.js";
|
|
17
17
|
import { DocumentationKind, getDocumentationKindColor } from "./DocumentationKind.js";
|
|
18
18
|
import { DocumentationParams } from "./DocumentationParams.js";
|
|
19
|
+
import { DocumentationProperties } from "./DocumentationProperties.js";
|
|
19
20
|
import { DocumentationReferences } from "./DocumentationReferences.js";
|
|
20
21
|
import { DocumentationReturns } from "./DocumentationReturns.js";
|
|
21
22
|
import { DocumentationSignatures } from "./DocumentationSignatures.js";
|
|
22
23
|
import { DocumentationThrows } from "./DocumentationThrows.js";
|
|
23
24
|
|
|
24
|
-
/** Documentation `kind`s grouped into card sections, in display order — pluralised, sentence-case headings. */
|
|
25
|
+
/** Documentation `kind`s grouped into card sections, in display order — pluralised, sentence-case headings. Data members (properties) are not child elements — they render as the Properties table instead. */
|
|
25
26
|
const KIND_SECTIONS = {
|
|
26
27
|
component: "Components",
|
|
27
28
|
function: "Functions",
|
|
@@ -30,9 +31,7 @@ const KIND_SECTIONS = {
|
|
|
30
31
|
type: "Types",
|
|
31
32
|
constant: "Constants",
|
|
32
33
|
"static method": "Static methods",
|
|
33
|
-
"static property": "Static properties",
|
|
34
34
|
method: "Methods",
|
|
35
|
-
property: "Properties",
|
|
36
35
|
};
|
|
37
36
|
|
|
38
37
|
/** Render a list of tree elements grouped into kind-based card sections, in `KIND_SECTIONS` order. */
|
|
@@ -68,11 +67,11 @@ function DocumentationChildren({ elements }: { readonly elements?: TreeElements
|
|
|
68
67
|
|
|
69
68
|
/**
|
|
70
69
|
* Page renderer for a `tree-documentation` element — the full detail page for a documented symbol.
|
|
71
|
-
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, referenced types, and examples.
|
|
72
|
-
* - In the Parameters / Returns / Throws tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A
|
|
73
|
-
* -
|
|
70
|
+
* - Renders breadcrumbs, title (with kind + `readonly` tags), relational links (`member of`, `extends`, `implements`), signatures (one per overload), content, parameters, returns, throws, properties, referenced types, and examples.
|
|
71
|
+
* - In the Parameters / Returns / Throws / Properties tables the `Type` column links each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text), and a row with no hand-written description falls back to the referenced type's own `description`. A default renders as a `Defaults to …` note (linking the value when it's a documented token) rather than in a dedicated column.
|
|
72
|
+
* - A class/interface/object-literal type's data members render as the Properties table (see `DocumentationProperties`); an options-bag parameter whose type resolves to one is flattened into indented child rows from the same structured list.
|
|
74
73
|
* - A `type` alias's referenced type names render as a linked `Type` table, each row carrying the resolved element's `description` (exact-match only).
|
|
75
|
-
* - Child symbols are grouped by `kind` into card sections
|
|
74
|
+
* - Child symbols (functions, classes, methods — not data members) are grouped by `kind` into card sections, each under its own heading.
|
|
76
75
|
* - All sections are conditional — only render when they have entries.
|
|
77
76
|
*
|
|
78
77
|
* @kind component
|
|
@@ -90,6 +89,7 @@ export function DocumentationPage({
|
|
|
90
89
|
params,
|
|
91
90
|
returns,
|
|
92
91
|
throws,
|
|
92
|
+
properties,
|
|
93
93
|
types,
|
|
94
94
|
examples,
|
|
95
95
|
children,
|
|
@@ -110,12 +110,13 @@ export function DocumentationPage({
|
|
|
110
110
|
<DocumentationButtons {...props} />
|
|
111
111
|
</Header>
|
|
112
112
|
</Panel>
|
|
113
|
-
{signatures?.length || params?.length || returns?.length || throws?.length || types?.length ? (
|
|
113
|
+
{signatures?.length || params?.length || returns?.length || throws?.length || properties?.length || types?.length ? (
|
|
114
114
|
<Section>
|
|
115
115
|
<DocumentationSignatures signatures={signatures} />
|
|
116
116
|
<DocumentationParams params={params} />
|
|
117
117
|
<DocumentationReturns returns={returns} />
|
|
118
118
|
<DocumentationThrows throws={throws} />
|
|
119
|
+
<DocumentationProperties properties={properties} />
|
|
119
120
|
<DocumentationReferences types={types} />
|
|
120
121
|
</Section>
|
|
121
122
|
) : null}
|