shelving 1.253.0 → 1.253.2
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/MetaContext.test.tsx +10 -0
- package/ui/misc/StatusIcon.md +10 -1
- package/ui/misc/StatusIcon.module.css +4 -0
- package/ui/misc/Tag.module.css +1 -1
- package/ui/router/Router.test.tsx +9 -0
- package/util/tree.d.ts +4 -2
- package/util/url.d.ts +3 -1
- package/util/url.js +4 -1
- package/ui/layout/Layout.module.css +0 -73
|
@@ -6,28 +6,13 @@ import { Scroll } from "../style/Scroll.js";
|
|
|
6
6
|
import { Cell } from "../table/Cell.js";
|
|
7
7
|
import { Table } from "../table/Table.js";
|
|
8
8
|
import { getTreeElement, useTreeMap } from "../tree/TreeContext.js";
|
|
9
|
-
import { TreeLink } from "../tree/TreeLink.js";
|
|
10
9
|
import { DocumentationDescription } from "./DocumentationDescription.js";
|
|
10
|
+
import { DocumentationType, splitType } from "./DocumentationType.js";
|
|
11
11
|
const DEFAULT_TYPE = "unknown";
|
|
12
12
|
/** Indentation (non-breaking spaces, so HTML doesn't collapse it) prefixed to a flattened sub-property's name so it reads as nested under its parent param. */
|
|
13
13
|
const SUBPARAM_INDENT = "\u00A0\u00A0\u00A0\u00A0";
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
* - An `undefined` member is dropped from display and instead flags the value as optional — we often write `| undefined` explicitly (e.g. for `exactOptionalPropertyTypes`, or to allow an explicit `undefined` to trigger a default), which reads as noise in the docs.
|
|
17
|
-
* - When nothing but `undefined` is left, the members are kept as-is rather than emptied.
|
|
18
|
-
*/
|
|
19
|
-
function _splitType(type) {
|
|
20
|
-
const parts = type
|
|
21
|
-
.split(" | ")
|
|
22
|
-
.map(part => part.trim())
|
|
23
|
-
.filter(Boolean);
|
|
24
|
-
const members = parts.filter(part => part !== "undefined");
|
|
25
|
-
return members.length ? { members, optional: members.length !== parts.length } : { members: parts, optional: false };
|
|
26
|
-
}
|
|
27
|
-
/** Render a type expression as one linked `Type`-column token per union member, each stacked on its own line (an `undefined` member is dropped — see `_splitType`). */
|
|
28
|
-
function _renderType(members) {
|
|
29
|
-
return members.map((member, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx("br", {}), _jsx(TreeLink, { name: member, nowrap: true })] }, member)));
|
|
30
|
-
}
|
|
14
|
+
/** Kinds whose `properties` represent an options-bag worth flattening into a param's child rows — interfaces and object-literal `type` aliases, not full classes. */
|
|
15
|
+
const FLATTEN_KINDS = new Set(["interface", "type"]);
|
|
31
16
|
/**
|
|
32
17
|
* Render a documented symbol's parameters as a scrollable table — one row per parameter.
|
|
33
18
|
* - Self-contained: pulls its own copy of the tree map from `useTreeMap()` so the `Type` column can link each type to its documented page via `TreeLink` (exact-match only; compound or builtin types stay plain text).
|
|
@@ -46,14 +31,15 @@ export function DocumentationParams({ params }) {
|
|
|
46
31
|
if (!params?.length)
|
|
47
32
|
return null;
|
|
48
33
|
return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Param" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: params.map(({ name, type = DEFAULT_TYPE, description, default: def, optional }) => {
|
|
49
|
-
const { members, optional: typeOptional } =
|
|
34
|
+
const { members, optional: typeOptional } = splitType(type);
|
|
50
35
|
// An options-bag param whose (single, concrete) type resolves to a documented interface/object type is flattened into its individual fields as indented child rows.
|
|
51
36
|
const single = members.length === 1 ? members[0] : undefined;
|
|
52
37
|
const resolved = single ? getTreeElement(map, single)?.props : undefined;
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
const properties = resolved && FLATTEN_KINDS.has(resolved.kind ?? "") ? resolved.properties : undefined;
|
|
39
|
+
return (_jsxs(Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { children: _jsx(Code, { nowrap: true, children: name }) }), _jsx("td", { children: _jsx(DocumentationType, { members: members }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || resolved?.description, default: def, optional: !!optional || typeOptional }) })] }), properties?.map(({ name: propName, type: propType = DEFAULT_TYPE, description: propDescription, default: propDef, optional: propOptional, readonly: propReadonly, }) => {
|
|
40
|
+
const { members: propMembers, optional: propTypeOptional } = splitType(propType);
|
|
55
41
|
const propSingle = propMembers[0] ?? DEFAULT_TYPE;
|
|
56
|
-
return (_jsxs("tr", { children: [_jsxs(Cell, { nowrap: true, children: [SUBPARAM_INDENT, _jsx(Code, { nowrap: true, children: `.${propName}` })] }), _jsx("td", { children:
|
|
42
|
+
return (_jsxs("tr", { children: [_jsxs(Cell, { nowrap: true, children: [SUBPARAM_INDENT, _jsx(Code, { nowrap: true, children: `.${propName}` })] }), _jsx("td", { children: _jsx(DocumentationType, { members: propMembers }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: propDescription || getTreeElement(map, propSingle)?.props.description, default: propDef, optional: !!propOptional || propTypeOptional, readonly: propReadonly }) })] }, `${propName}-${propType}-${propDescription}`));
|
|
57
43
|
})] }, `${name}-${type}`));
|
|
58
44
|
}) })] }) }) }));
|
|
59
45
|
}
|
|
@@ -7,37 +7,16 @@ import { Scroll } from "../style/Scroll.js";
|
|
|
7
7
|
import { Cell } from "../table/Cell.js";
|
|
8
8
|
import { Table } from "../table/Table.js";
|
|
9
9
|
import { getTreeElement, useTreeMap } from "../tree/TreeContext.js";
|
|
10
|
-
import { TreeLink } from "../tree/TreeLink.js";
|
|
11
10
|
import { DocumentationDescription } from "./DocumentationDescription.js";
|
|
11
|
+
import { DocumentationType, splitType } from "./DocumentationType.js";
|
|
12
12
|
|
|
13
13
|
const DEFAULT_TYPE = "unknown";
|
|
14
14
|
|
|
15
15
|
/** Indentation (non-breaking spaces, so HTML doesn't collapse it) prefixed to a flattened sub-property's name so it reads as nested under its parent param. */
|
|
16
16
|
const SUBPARAM_INDENT = "\u00A0\u00A0\u00A0\u00A0";
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
* - An `undefined` member is dropped from display and instead flags the value as optional — we often write `| undefined` explicitly (e.g. for `exactOptionalPropertyTypes`, or to allow an explicit `undefined` to trigger a default), which reads as noise in the docs.
|
|
21
|
-
* - When nothing but `undefined` is left, the members are kept as-is rather than emptied.
|
|
22
|
-
*/
|
|
23
|
-
function _splitType(type: string): { readonly members: readonly string[]; readonly optional: boolean } {
|
|
24
|
-
const parts = type
|
|
25
|
-
.split(" | ")
|
|
26
|
-
.map(part => part.trim())
|
|
27
|
-
.filter(Boolean);
|
|
28
|
-
const members = parts.filter(part => part !== "undefined");
|
|
29
|
-
return members.length ? { members, optional: members.length !== parts.length } : { members: parts, optional: false };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** Render a type expression as one linked `Type`-column token per union member, each stacked on its own line (an `undefined` member is dropped — see `_splitType`). */
|
|
33
|
-
function _renderType(members: readonly string[]): ReactNode {
|
|
34
|
-
return members.map((member, index) => (
|
|
35
|
-
<Fragment key={member}>
|
|
36
|
-
{index > 0 && <br />}
|
|
37
|
-
<TreeLink name={member} nowrap />
|
|
38
|
-
</Fragment>
|
|
39
|
-
));
|
|
40
|
-
}
|
|
18
|
+
/** Kinds whose `properties` represent an options-bag worth flattening into a param's child rows — interfaces and object-literal `type` aliases, not full classes. */
|
|
19
|
+
const FLATTEN_KINDS = new Set(["interface", "type"]);
|
|
41
20
|
|
|
42
21
|
/**
|
|
43
22
|
* Props for `DocumentationParams` — the parameter list to render, one row per parameter.
|
|
@@ -82,17 +61,20 @@ export function DocumentationParams({ params }: DocumentationParamsProps): React
|
|
|
82
61
|
</thead>
|
|
83
62
|
<tbody>
|
|
84
63
|
{params.map(({ name, type = DEFAULT_TYPE, description, default: def, optional }) => {
|
|
85
|
-
const { members, optional: typeOptional } =
|
|
64
|
+
const { members, optional: typeOptional } = splitType(type);
|
|
86
65
|
// An options-bag param whose (single, concrete) type resolves to a documented interface/object type is flattened into its individual fields as indented child rows.
|
|
87
66
|
const single = members.length === 1 ? members[0] : undefined;
|
|
88
67
|
const resolved = single ? (getTreeElement(map, single)?.props as DocumentationElementProps | undefined) : undefined;
|
|
68
|
+
const properties = resolved && FLATTEN_KINDS.has(resolved.kind ?? "") ? resolved.properties : undefined;
|
|
89
69
|
return (
|
|
90
70
|
<Fragment key={`${name}-${type}`}>
|
|
91
71
|
<tr>
|
|
92
72
|
<td>
|
|
93
73
|
<Code nowrap>{name}</Code>
|
|
94
74
|
</td>
|
|
95
|
-
<td>
|
|
75
|
+
<td>
|
|
76
|
+
<DocumentationType members={members} />
|
|
77
|
+
</td>
|
|
96
78
|
<td>
|
|
97
79
|
<DocumentationDescription
|
|
98
80
|
description={description || resolved?.description}
|
|
@@ -101,15 +83,16 @@ export function DocumentationParams({ params }: DocumentationParamsProps): React
|
|
|
101
83
|
/>
|
|
102
84
|
</td>
|
|
103
85
|
</tr>
|
|
104
|
-
{
|
|
86
|
+
{properties?.map(
|
|
105
87
|
({
|
|
106
88
|
name: propName,
|
|
107
89
|
type: propType = DEFAULT_TYPE,
|
|
108
90
|
description: propDescription,
|
|
109
91
|
default: propDef,
|
|
110
92
|
optional: propOptional,
|
|
93
|
+
readonly: propReadonly,
|
|
111
94
|
}) => {
|
|
112
|
-
const { members: propMembers, optional: propTypeOptional } =
|
|
95
|
+
const { members: propMembers, optional: propTypeOptional } = splitType(propType);
|
|
113
96
|
const propSingle = propMembers[0] ?? DEFAULT_TYPE;
|
|
114
97
|
return (
|
|
115
98
|
<tr key={`${propName}-${propType}-${propDescription}`}>
|
|
@@ -117,12 +100,15 @@ export function DocumentationParams({ params }: DocumentationParamsProps): React
|
|
|
117
100
|
{SUBPARAM_INDENT}
|
|
118
101
|
<Code nowrap>{`.${propName}`}</Code>
|
|
119
102
|
</Cell>
|
|
120
|
-
<td>
|
|
103
|
+
<td>
|
|
104
|
+
<DocumentationType members={propMembers} />
|
|
105
|
+
</td>
|
|
121
106
|
<td>
|
|
122
107
|
<DocumentationDescription
|
|
123
108
|
description={propDescription || getTreeElement(map, propSingle)?.props.description}
|
|
124
109
|
default={propDef}
|
|
125
110
|
optional={!!propOptional || propTypeOptional}
|
|
111
|
+
readonly={propReadonly}
|
|
126
112
|
/>
|
|
127
113
|
</td>
|
|
128
114
|
</tr>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ImmutableArray } from "../../util/array.js";
|
|
3
|
+
import type { DocumentationParam } from "../../util/tree.js";
|
|
4
|
+
/**
|
|
5
|
+
* Props for `DocumentationProperties` — the data members of a class/interface/object-literal type to render, one row each.
|
|
6
|
+
*
|
|
7
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationProperties/DocumentationPropertiesProps
|
|
8
|
+
*/
|
|
9
|
+
export interface DocumentationPropertiesProps {
|
|
10
|
+
/** Properties to render — one row each. */
|
|
11
|
+
readonly properties?: ImmutableArray<DocumentationParam> | undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Render a documented type's data members (properties, getters/setters) as a scrollable table — one row per property.
|
|
15
|
+
* - Self-contained: pulls its own copy of the tree map from [`useTreeMap()`](/ui/useTreeMap) so the `Type` column can link each type to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
16
|
+
* - Each property name carries a leading `.` (e.g. `.caller`); a union type renders one linked token per member, each on its own line, with a `| undefined` member dropped and marking the property optional.
|
|
17
|
+
* - Descriptions render as inline markup, with a trailing `Defaults to …` (linked when documented) or `Required.` note — see [`DocumentationDescription`](/ui/DocumentationDescription). A row with no hand-written description falls back to the referenced type's own `description`.
|
|
18
|
+
* - These are the same structured entries an options-bag parameter is flattened from in [`DocumentationParams`](/ui/DocumentationParams), so the two stay in sync by construction.
|
|
19
|
+
* - Renders nothing when there are no properties.
|
|
20
|
+
*
|
|
21
|
+
* @kind component
|
|
22
|
+
* @returns A [`<Section>`](/ui/Section) containing the properties table, or `null` when there are none.
|
|
23
|
+
* @example <DocumentationProperties properties={properties} />
|
|
24
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationProperties/DocumentationProperties
|
|
25
|
+
*/
|
|
26
|
+
export declare function DocumentationProperties({ properties }: DocumentationPropertiesProps): ReactNode;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Section } from "../block/Section.js";
|
|
3
|
+
import { Code } from "../inline/Code.js";
|
|
4
|
+
import { Scroll } from "../style/Scroll.js";
|
|
5
|
+
import { Cell } from "../table/Cell.js";
|
|
6
|
+
import { Table } from "../table/Table.js";
|
|
7
|
+
import { getTreeElement, useTreeMap } from "../tree/TreeContext.js";
|
|
8
|
+
import { DocumentationDescription } from "./DocumentationDescription.js";
|
|
9
|
+
import { DocumentationType, splitType } from "./DocumentationType.js";
|
|
10
|
+
const DEFAULT_TYPE = "unknown";
|
|
11
|
+
/**
|
|
12
|
+
* Render a documented type's data members (properties, getters/setters) as a scrollable table — one row per property.
|
|
13
|
+
* - Self-contained: pulls its own copy of the tree map from [`useTreeMap()`](/ui/useTreeMap) so the `Type` column can link each type to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
14
|
+
* - Each property name carries a leading `.` (e.g. `.caller`); a union type renders one linked token per member, each on its own line, with a `| undefined` member dropped and marking the property optional.
|
|
15
|
+
* - Descriptions render as inline markup, with a trailing `Defaults to …` (linked when documented) or `Required.` note — see [`DocumentationDescription`](/ui/DocumentationDescription). A row with no hand-written description falls back to the referenced type's own `description`.
|
|
16
|
+
* - These are the same structured entries an options-bag parameter is flattened from in [`DocumentationParams`](/ui/DocumentationParams), so the two stay in sync by construction.
|
|
17
|
+
* - Renders nothing when there are no properties.
|
|
18
|
+
*
|
|
19
|
+
* @kind component
|
|
20
|
+
* @returns A [`<Section>`](/ui/Section) containing the properties table, or `null` when there are none.
|
|
21
|
+
* @example <DocumentationProperties properties={properties} />
|
|
22
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationProperties/DocumentationProperties
|
|
23
|
+
*/
|
|
24
|
+
export function DocumentationProperties({ properties }) {
|
|
25
|
+
const map = useTreeMap();
|
|
26
|
+
if (!properties?.length)
|
|
27
|
+
return null;
|
|
28
|
+
return (_jsx(Section, { children: _jsx(Scroll, { horizontal: true, children: _jsxs(Table, { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx(Cell, { header: true, width: "fit", children: "Property" }), _jsx(Cell, { header: true, width: "fit", children: "Type" }), _jsx(Cell, { header: true, width: "xxnarrow", grow: true })] }) }), _jsx("tbody", { children: properties.map(({ name, type = DEFAULT_TYPE, description, default: def, optional, readonly }) => {
|
|
29
|
+
const { members, optional: typeOptional } = splitType(type);
|
|
30
|
+
return (_jsxs("tr", { children: [_jsx(Cell, { nowrap: true, children: _jsx(Code, { nowrap: true, children: `.${name}` }) }), _jsx("td", { children: _jsx(DocumentationType, { members: members }) }), _jsx("td", { children: _jsx(DocumentationDescription, { description: description || getTreeElement(map, members[0] ?? DEFAULT_TYPE)?.props.description, default: def, optional: !!optional || typeOptional, readonly: readonly }) })] }, `${name}-${type}`));
|
|
31
|
+
}) })] }) }) }));
|
|
32
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { ImmutableArray } from "../../util/array.js";
|
|
3
|
+
import type { DocumentationParam } from "../../util/tree.js";
|
|
4
|
+
import { Section } from "../block/Section.js";
|
|
5
|
+
import { Code } from "../inline/Code.js";
|
|
6
|
+
import { Scroll } from "../style/Scroll.js";
|
|
7
|
+
import { Cell } from "../table/Cell.js";
|
|
8
|
+
import { Table } from "../table/Table.js";
|
|
9
|
+
import { getTreeElement, useTreeMap } from "../tree/TreeContext.js";
|
|
10
|
+
import { DocumentationDescription } from "./DocumentationDescription.js";
|
|
11
|
+
import { DocumentationType, splitType } from "./DocumentationType.js";
|
|
12
|
+
|
|
13
|
+
const DEFAULT_TYPE = "unknown";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Props for `DocumentationProperties` — the data members of a class/interface/object-literal type to render, one row each.
|
|
17
|
+
*
|
|
18
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationProperties/DocumentationPropertiesProps
|
|
19
|
+
*/
|
|
20
|
+
export interface DocumentationPropertiesProps {
|
|
21
|
+
/** Properties to render — one row each. */
|
|
22
|
+
readonly properties?: ImmutableArray<DocumentationParam> | undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Render a documented type's data members (properties, getters/setters) as a scrollable table — one row per property.
|
|
27
|
+
* - Self-contained: pulls its own copy of the tree map from [`useTreeMap()`](/ui/useTreeMap) so the `Type` column can link each type to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
28
|
+
* - Each property name carries a leading `.` (e.g. `.caller`); a union type renders one linked token per member, each on its own line, with a `| undefined` member dropped and marking the property optional.
|
|
29
|
+
* - Descriptions render as inline markup, with a trailing `Defaults to …` (linked when documented) or `Required.` note — see [`DocumentationDescription`](/ui/DocumentationDescription). A row with no hand-written description falls back to the referenced type's own `description`.
|
|
30
|
+
* - These are the same structured entries an options-bag parameter is flattened from in [`DocumentationParams`](/ui/DocumentationParams), so the two stay in sync by construction.
|
|
31
|
+
* - Renders nothing when there are no properties.
|
|
32
|
+
*
|
|
33
|
+
* @kind component
|
|
34
|
+
* @returns A [`<Section>`](/ui/Section) containing the properties table, or `null` when there are none.
|
|
35
|
+
* @example <DocumentationProperties properties={properties} />
|
|
36
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationProperties/DocumentationProperties
|
|
37
|
+
*/
|
|
38
|
+
export function DocumentationProperties({ properties }: DocumentationPropertiesProps): ReactNode {
|
|
39
|
+
const map = useTreeMap();
|
|
40
|
+
if (!properties?.length) return null;
|
|
41
|
+
return (
|
|
42
|
+
<Section>
|
|
43
|
+
<Scroll horizontal>
|
|
44
|
+
<Table>
|
|
45
|
+
<thead>
|
|
46
|
+
<tr>
|
|
47
|
+
<Cell header width="fit">
|
|
48
|
+
Property
|
|
49
|
+
</Cell>
|
|
50
|
+
<Cell header width="fit">
|
|
51
|
+
Type
|
|
52
|
+
</Cell>
|
|
53
|
+
<Cell header width="xxnarrow" grow />
|
|
54
|
+
</tr>
|
|
55
|
+
</thead>
|
|
56
|
+
<tbody>
|
|
57
|
+
{properties.map(({ name, type = DEFAULT_TYPE, description, default: def, optional, readonly }) => {
|
|
58
|
+
const { members, optional: typeOptional } = splitType(type);
|
|
59
|
+
return (
|
|
60
|
+
<tr key={`${name}-${type}`}>
|
|
61
|
+
<Cell nowrap>
|
|
62
|
+
<Code nowrap>{`.${name}`}</Code>
|
|
63
|
+
</Cell>
|
|
64
|
+
<td>
|
|
65
|
+
<DocumentationType members={members} />
|
|
66
|
+
</td>
|
|
67
|
+
<td>
|
|
68
|
+
<DocumentationDescription
|
|
69
|
+
description={description || getTreeElement(map, members[0] ?? DEFAULT_TYPE)?.props.description}
|
|
70
|
+
default={def}
|
|
71
|
+
optional={!!optional || typeOptional}
|
|
72
|
+
readonly={readonly}
|
|
73
|
+
/>
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
);
|
|
77
|
+
})}
|
|
78
|
+
</tbody>
|
|
79
|
+
</Table>
|
|
80
|
+
</Scroll>
|
|
81
|
+
</Section>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Split a type expression on ` | ` into its individual union members.
|
|
4
|
+
* - An `undefined` member is dropped from display and instead flags the value as optional — we often write `| undefined` explicitly (e.g. for `exactOptionalPropertyTypes`, or to allow an explicit `undefined` to trigger a default), which reads as noise in the docs.
|
|
5
|
+
* - When nothing but `undefined` is left, the members are kept as-is rather than emptied.
|
|
6
|
+
*
|
|
7
|
+
* @param type The type expression to split (e.g. `"Schemas<T> | DataSchema<T>"`).
|
|
8
|
+
* @returns The non-`undefined` members, plus whether an `undefined` member was dropped.
|
|
9
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/splitType
|
|
10
|
+
*/
|
|
11
|
+
export declare function splitType(type: string): {
|
|
12
|
+
readonly members: readonly string[];
|
|
13
|
+
readonly optional: boolean;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Props for `DocumentationType` — the union members to render (see [`splitType`](/ui/splitType)).
|
|
17
|
+
*
|
|
18
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/DocumentationTypeProps
|
|
19
|
+
*/
|
|
20
|
+
export interface DocumentationTypeProps {
|
|
21
|
+
/** Union members to render — one linked token each, stacked on their own line. */
|
|
22
|
+
readonly members: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Render a documentation table's `Type` column — one linked token per union member, each stacked on its own line.
|
|
26
|
+
* - Each member links to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
27
|
+
*
|
|
28
|
+
* @kind component
|
|
29
|
+
* @returns One [`TreeLink`](/ui/TreeLink) per member, separated by line breaks.
|
|
30
|
+
* @example <DocumentationType members={["Schemas<T>", "DataSchema<T>"]} />
|
|
31
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/DocumentationType
|
|
32
|
+
*/
|
|
33
|
+
export declare function DocumentationType({ members }: DocumentationTypeProps): ReactNode;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment } from "react";
|
|
3
|
+
import { TreeLink } from "../tree/TreeLink.js";
|
|
4
|
+
/**
|
|
5
|
+
* Split a type expression on ` | ` into its individual union members.
|
|
6
|
+
* - An `undefined` member is dropped from display and instead flags the value as optional — we often write `| undefined` explicitly (e.g. for `exactOptionalPropertyTypes`, or to allow an explicit `undefined` to trigger a default), which reads as noise in the docs.
|
|
7
|
+
* - When nothing but `undefined` is left, the members are kept as-is rather than emptied.
|
|
8
|
+
*
|
|
9
|
+
* @param type The type expression to split (e.g. `"Schemas<T> | DataSchema<T>"`).
|
|
10
|
+
* @returns The non-`undefined` members, plus whether an `undefined` member was dropped.
|
|
11
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/splitType
|
|
12
|
+
*/
|
|
13
|
+
export function splitType(type) {
|
|
14
|
+
const parts = type
|
|
15
|
+
.split(" | ")
|
|
16
|
+
.map(part => part.trim())
|
|
17
|
+
.filter(Boolean);
|
|
18
|
+
const members = parts.filter(part => part !== "undefined");
|
|
19
|
+
return members.length ? { members, optional: members.length !== parts.length } : { members: parts, optional: false };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Render a documentation table's `Type` column — one linked token per union member, each stacked on its own line.
|
|
23
|
+
* - Each member links to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
24
|
+
*
|
|
25
|
+
* @kind component
|
|
26
|
+
* @returns One [`TreeLink`](/ui/TreeLink) per member, separated by line breaks.
|
|
27
|
+
* @example <DocumentationType members={["Schemas<T>", "DataSchema<T>"]} />
|
|
28
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/DocumentationType
|
|
29
|
+
*/
|
|
30
|
+
export function DocumentationType({ members }) {
|
|
31
|
+
return members.map((member, index) => (_jsxs(Fragment, { children: [index > 0 && _jsx("br", {}), _jsx(TreeLink, { name: member, nowrap: true })] }, member)));
|
|
32
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Fragment, type ReactNode } from "react";
|
|
2
|
+
import { TreeLink } from "../tree/TreeLink.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Split a type expression on ` | ` into its individual union members.
|
|
6
|
+
* - An `undefined` member is dropped from display and instead flags the value as optional — we often write `| undefined` explicitly (e.g. for `exactOptionalPropertyTypes`, or to allow an explicit `undefined` to trigger a default), which reads as noise in the docs.
|
|
7
|
+
* - When nothing but `undefined` is left, the members are kept as-is rather than emptied.
|
|
8
|
+
*
|
|
9
|
+
* @param type The type expression to split (e.g. `"Schemas<T> | DataSchema<T>"`).
|
|
10
|
+
* @returns The non-`undefined` members, plus whether an `undefined` member was dropped.
|
|
11
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/splitType
|
|
12
|
+
*/
|
|
13
|
+
export function splitType(type: string): { readonly members: readonly string[]; readonly optional: boolean } {
|
|
14
|
+
const parts = type
|
|
15
|
+
.split(" | ")
|
|
16
|
+
.map(part => part.trim())
|
|
17
|
+
.filter(Boolean);
|
|
18
|
+
const members = parts.filter(part => part !== "undefined");
|
|
19
|
+
return members.length ? { members, optional: members.length !== parts.length } : { members: parts, optional: false };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Props for `DocumentationType` — the union members to render (see [`splitType`](/ui/splitType)).
|
|
24
|
+
*
|
|
25
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/DocumentationTypeProps
|
|
26
|
+
*/
|
|
27
|
+
export interface DocumentationTypeProps {
|
|
28
|
+
/** Union members to render — one linked token each, stacked on their own line. */
|
|
29
|
+
readonly members: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Render a documentation table's `Type` column — one linked token per union member, each stacked on its own line.
|
|
34
|
+
* - Each member links to its documented page via [`TreeLink`](/ui/TreeLink) (exact-match only; compound or builtin types stay plain text).
|
|
35
|
+
*
|
|
36
|
+
* @kind component
|
|
37
|
+
* @returns One [`TreeLink`](/ui/TreeLink) per member, separated by line breaks.
|
|
38
|
+
* @example <DocumentationType members={["Schemas<T>", "DataSchema<T>"]} />
|
|
39
|
+
* @see https://dhoulb.github.io/shelving/ui/docs/DocumentationType/DocumentationType
|
|
40
|
+
*/
|
|
41
|
+
export function DocumentationType({ members }: DocumentationTypeProps): ReactNode {
|
|
42
|
+
return members.map((member, index) => (
|
|
43
|
+
<Fragment key={member}>
|
|
44
|
+
{index > 0 && <br />}
|
|
45
|
+
<TreeLink name={member} nowrap />
|
|
46
|
+
</Fragment>
|
|
47
|
+
));
|
|
48
|
+
}
|
package/ui/docs/index.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ export * from "./DocumentationHomePage.js";
|
|
|
5
5
|
export * from "./DocumentationKind.js";
|
|
6
6
|
export * from "./DocumentationPage.js";
|
|
7
7
|
export * from "./DocumentationParams.js";
|
|
8
|
+
export * from "./DocumentationProperties.js";
|
|
8
9
|
export * from "./DocumentationReferences.js";
|
|
9
10
|
export * from "./DocumentationReturns.js";
|
|
10
11
|
export * from "./DocumentationSignatures.js";
|
|
11
12
|
export * from "./DocumentationThrows.js";
|
|
13
|
+
export * from "./DocumentationType.js";
|
package/ui/docs/index.js
CHANGED
|
@@ -5,7 +5,9 @@ export * from "./DocumentationHomePage.js";
|
|
|
5
5
|
export * from "./DocumentationKind.js";
|
|
6
6
|
export * from "./DocumentationPage.js";
|
|
7
7
|
export * from "./DocumentationParams.js";
|
|
8
|
+
export * from "./DocumentationProperties.js";
|
|
8
9
|
export * from "./DocumentationReferences.js";
|
|
9
10
|
export * from "./DocumentationReturns.js";
|
|
10
11
|
export * from "./DocumentationSignatures.js";
|
|
11
12
|
export * from "./DocumentationThrows.js";
|
|
13
|
+
export * from "./DocumentationType.js";
|
package/ui/docs/index.ts
CHANGED
|
@@ -5,7 +5,9 @@ export * from "./DocumentationHomePage.js";
|
|
|
5
5
|
export * from "./DocumentationKind.js";
|
|
6
6
|
export * from "./DocumentationPage.js";
|
|
7
7
|
export * from "./DocumentationParams.js";
|
|
8
|
+
export * from "./DocumentationProperties.js";
|
|
8
9
|
export * from "./DocumentationReferences.js";
|
|
9
10
|
export * from "./DocumentationReturns.js";
|
|
10
11
|
export * from "./DocumentationSignatures.js";
|
|
11
12
|
export * from "./DocumentationThrows.js";
|
|
13
|
+
export * from "./DocumentationType.js";
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { RouteCache } from "../router/RouteCache.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getModuleClass } from "../util/css.js";
|
|
4
4
|
import CENTERED_LAYOUT_CSS from "./CenteredLayout.module.css";
|
|
5
|
-
import { LAYOUT_CLASS } from "./Layout.js";
|
|
6
5
|
/**
|
|
7
6
|
* Layout that centres its content with no header/footer and a narrow max-width.
|
|
8
7
|
* - Used for e.g. login/register/error/form pages where the content is the only focus.
|
|
@@ -17,5 +16,5 @@ import { LAYOUT_CLASS } from "./Layout.js";
|
|
|
17
16
|
export function CenteredLayout({ children, fullWidth = false }) {
|
|
18
17
|
// Wrap the scrolling `<main>` in `<RouteCache>` so recently-visited pages stay mounted but hidden,
|
|
19
18
|
// keeping their scroll position and state intact across back/forward navigation.
|
|
20
|
-
return (_jsx(RouteCache, { children: _jsx("main", { className:
|
|
19
|
+
return (_jsx(RouteCache, { children: _jsx("main", { className: getModuleClass(CENTERED_LAYOUT_CSS, "main"), children: _jsx("div", { className: getModuleClass(CENTERED_LAYOUT_CSS, "mainInner"), style: fullWidth ? { maxWidth: "none" } : undefined, children: children }) }) }));
|
|
21
20
|
}
|
|
@@ -27,6 +27,6 @@ Layouts compose naturally as `<Router>` route values — wrap a group of routes
|
|
|
27
27
|
|
|
28
28
|
## Styling
|
|
29
29
|
|
|
30
|
-
This layout exposes no own `--centered-layout-*` hooks. The inner column is capped at the global `--width-wide` token (dropped when `fullWidth` is set), and the outer element
|
|
30
|
+
This layout exposes no own `--centered-layout-*` hooks. The inner column is capped at the global `--width-wide` token (dropped when `fullWidth` is set), and the outer element owns its scroll, padding, and safe-area behaviour directly — reading the layout hooks `--layout-space`, `--layout-padding`, `--layout-body-bg`, and `--layout-inset-top` / `-bottom` / `-left` / `-right`.
|
|
31
31
|
|
|
32
32
|
**Global tokens it reads** — `--width-wide`.
|
|
@@ -1,13 +1,73 @@
|
|
|
1
1
|
@import "../style/layers.css";
|
|
2
|
+
@import "../style/Space.module.css";
|
|
3
|
+
@import "../style/Tint.module.css";
|
|
2
4
|
@import "../style/Width.module.css";
|
|
3
5
|
|
|
6
|
+
/* Low-priority padding defaults live in `@layer defaults` so consumers can override them */
|
|
7
|
+
/* with normal-specificity selectors without needing `:where()` tricks. */
|
|
8
|
+
@layer defaults {
|
|
9
|
+
.main {
|
|
10
|
+
/* Top/bottom use `layout-space` and left/right use `layout-padding`, plus safe-area additions. */
|
|
11
|
+
padding: var(--layout-space, var(--space-normal)) var(--layout-padding, var(--space-normal));
|
|
12
|
+
padding-top: calc(var(--layout-space, var(--space-normal)) + max(var(--layout-inset-top, 0px), env(safe-area-inset-top, 0px)));
|
|
13
|
+
padding-bottom: calc(var(--layout-space, var(--space-normal)) + max(var(--layout-inset-bottom, 0px), env(safe-area-inset-bottom, 0px)));
|
|
14
|
+
padding-left: calc(var(--layout-padding, var(--space-normal)) + max(var(--layout-inset-left, 0px), env(safe-area-inset-left, 0px)));
|
|
15
|
+
padding-right: calc(var(--layout-padding, var(--space-normal)) + max(var(--layout-inset-right, 0px), env(safe-area-inset-right, 0px)));
|
|
16
|
+
|
|
17
|
+
/* Grow to fill the body. */
|
|
18
|
+
flex: 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
4
22
|
@layer components {
|
|
23
|
+
/*
|
|
24
|
+
* Lock the document and let `.main` own the page scroll.
|
|
25
|
+
* - <html> and <body> are pinned to the viewport (no rubber-band on iOS).
|
|
26
|
+
* - <body> stacks its children vertically (flex column).
|
|
27
|
+
* - The `.main` element grows to fill the body and is the only scroll container.
|
|
28
|
+
*/
|
|
29
|
+
html:has(.main) {
|
|
30
|
+
/* Box */
|
|
31
|
+
margin: 0;
|
|
32
|
+
padding: 0;
|
|
33
|
+
height: 100vh;
|
|
34
|
+
height: 100dvh; /* Make the height dynamically expand/contract as the address bar shows/hides on iOS. */
|
|
35
|
+
width: 100vw;
|
|
36
|
+
width: 100dvw;
|
|
37
|
+
|
|
38
|
+
/* Contents */
|
|
39
|
+
overflow: hidden;
|
|
40
|
+
overflow-wrap: break-word; /* Break overlong words only as a last resort. */
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
body:has(.main) {
|
|
44
|
+
/* Box */
|
|
45
|
+
margin: 0;
|
|
46
|
+
padding: 0;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
|
|
50
|
+
/* Lock body to prevent iOS Safari triggering viewport scrolling on focus change. */
|
|
51
|
+
position: fixed;
|
|
52
|
+
inset: 0;
|
|
53
|
+
|
|
54
|
+
/* Layout-specific bg hook. */
|
|
55
|
+
background: var(--layout-body-bg, var(--tint-100));
|
|
56
|
+
}
|
|
57
|
+
|
|
5
58
|
.main {
|
|
6
|
-
/* Content */
|
|
59
|
+
/* Content — a flex column whose inner column centres itself with `margin: auto` (both axes). */
|
|
7
60
|
display: flex;
|
|
8
61
|
flex-direction: column;
|
|
9
62
|
align-items: center;
|
|
10
63
|
justify-content: start;
|
|
64
|
+
|
|
65
|
+
/* Scrolling */
|
|
66
|
+
overflow-x: hidden;
|
|
67
|
+
overflow-y: auto;
|
|
68
|
+
overscroll-behavior-x: auto;
|
|
69
|
+
overscroll-behavior-y: contain;
|
|
70
|
+
scroll-behavior: smooth;
|
|
11
71
|
}
|
|
12
72
|
|
|
13
73
|
.mainInner {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import { RouteCache } from "../router/RouteCache.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getModuleClass } from "../util/css.js";
|
|
4
4
|
import type { OptionalChildProps } from "../util/props.js";
|
|
5
5
|
import CENTERED_LAYOUT_CSS from "./CenteredLayout.module.css";
|
|
6
|
-
import { LAYOUT_CLASS } from "./Layout.js";
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Props for `<CenteredLayout>` — optional `children` and a `fullWidth` flag to drop the max-width.
|
|
@@ -30,7 +29,7 @@ export function CenteredLayout({ children, fullWidth = false }: CenteredLayoutPr
|
|
|
30
29
|
// keeping their scroll position and state intact across back/forward navigation.
|
|
31
30
|
return (
|
|
32
31
|
<RouteCache>
|
|
33
|
-
<main className={
|
|
32
|
+
<main className={getModuleClass(CENTERED_LAYOUT_CSS, "main")}>
|
|
34
33
|
<div className={getModuleClass(CENTERED_LAYOUT_CSS, "mainInner")} style={fullWidth ? { maxWidth: "none" } : undefined}>
|
|
35
34
|
{children}
|
|
36
35
|
</div>
|
package/ui/layout/Layout.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolved `.layout` class for composing the layout's padding/scroll/safe-area behaviour onto a custom element.
|
|
3
|
-
*
|
|
4
|
-
* @example <main className={LAYOUT_CLASS}>…</main>
|
|
5
|
-
* @see https://dhoulb.github.io/shelving/ui/layout/Layout/LAYOUT_CLASS
|
|
6
|
-
*/
|
|
7
|
-
export declare const LAYOUT_CLASS: string | undefined;
|
|
8
1
|
/**
|
|
9
2
|
* Track the dynamic viewport height so layout safe-area insets follow the on-screen keyboard.
|
|
10
3
|
*
|
package/ui/layout/Layout.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import { getModuleClass } from "../util/css.js";
|
|
2
|
-
import styles from "./Layout.module.css";
|
|
3
|
-
/**
|
|
4
|
-
* Resolved `.layout` class for composing the layout's padding/scroll/safe-area behaviour onto a custom element.
|
|
5
|
-
*
|
|
6
|
-
* @example <main className={LAYOUT_CLASS}>…</main>
|
|
7
|
-
* @see https://dhoulb.github.io/shelving/ui/layout/Layout/LAYOUT_CLASS
|
|
8
|
-
*/
|
|
9
|
-
export const LAYOUT_CLASS = getModuleClass(styles, "layout");
|
|
10
1
|
/**
|
|
11
2
|
* Track the dynamic viewport height so layout safe-area insets follow the on-screen keyboard.
|
|
12
3
|
*
|
package/ui/layout/Layout.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
import { getModuleClass } from "../util/css.js";
|
|
2
|
-
import styles from "./Layout.module.css";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Resolved `.layout` class for composing the layout's padding/scroll/safe-area behaviour onto a custom element.
|
|
6
|
-
*
|
|
7
|
-
* @example <main className={LAYOUT_CLASS}>…</main>
|
|
8
|
-
* @see https://dhoulb.github.io/shelving/ui/layout/Layout/LAYOUT_CLASS
|
|
9
|
-
*/
|
|
10
|
-
export const LAYOUT_CLASS = getModuleClass(styles, "layout");
|
|
11
|
-
|
|
12
1
|
/**
|
|
13
2
|
* Track the dynamic viewport height so layout safe-area insets follow the on-screen keyboard.
|
|
14
3
|
*
|
|
@@ -5,7 +5,6 @@ import { Button } from "../form/Button.js";
|
|
|
5
5
|
import { requireMetaURL } from "../misc/MetaContext.js";
|
|
6
6
|
import { RouteCache } from "../router/RouteCache.js";
|
|
7
7
|
import { getClass, getModuleClass } from "../util/css.js";
|
|
8
|
-
import { LAYOUT_CLASS } from "./Layout.js";
|
|
9
8
|
import SIDEBAR_LAYOUT_CSS from "./SidebarLayout.module.css";
|
|
10
9
|
/**
|
|
11
10
|
* Layout with a fixed-width side column (typically navigation) next to a scrollable main content column.
|
|
@@ -37,7 +36,7 @@ export function SidebarLayout({ sidebar, children, right = false }) {
|
|
|
37
36
|
// — keeping the scroll position of this `.content` container (and all page state) intact across
|
|
38
37
|
// back/forward navigation. The sidebar and drawer state stay outside the cache, so they are neither
|
|
39
38
|
// duplicated nor remounted as the URL changes.
|
|
40
|
-
const contentEl = (_jsx(RouteCache, { children: _jsxs("div", { className:
|
|
39
|
+
const contentEl = (_jsx(RouteCache, { children: _jsxs("div", { className: getModuleClass(SIDEBAR_LAYOUT_CSS, "content"), children: [_jsx("div", { className: getModuleClass(SIDEBAR_LAYOUT_CSS, "toggle"), children: _jsx(Button, { title: open ? "Close menu" : "Show menu", onClick: () => setOpen(o => !o), children: open ? _jsx(XMarkIcon, {}) : _jsx(Bars3Icon, {}) }) }), _jsx("div", { className: getModuleClass(SIDEBAR_LAYOUT_CSS, "contentInner"), children: children })] }) }, "content"));
|
|
41
40
|
const overlayEl = open && (_jsx("button", { type: "button", className: getModuleClass(SIDEBAR_LAYOUT_CSS, "overlay"), "aria-label": "Close menu", onClick: () => setOpen(false) }, "overlay"));
|
|
42
|
-
return (_jsx("main", { className:
|
|
41
|
+
return (_jsx("main", { className: getModuleClass(SIDEBAR_LAYOUT_CSS, "main"), children: right ? [contentEl, sidebarEl, overlayEl] : [sidebarEl, contentEl, overlayEl] }));
|
|
43
42
|
}
|