@structuralists/scaffolding 0.3.0 → 0.4.0
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/package.json +1 -1
- package/src/components/Json/JsonTable/JsonLeafNode.tsx +9 -3
- package/src/components/Json/JsonTable/index.tsx +23 -7
- package/src/components/Json/JsonTable/styles.module.css +7 -0
- package/src/components/Json/JsonTable/types.ts +12 -3
- package/src/components/Tables/QuickTable/index.tsx +20 -6
- package/src/components/Tables/QuickTable/styles.module.css +8 -0
- package/src/components/Tables/QuickTable/types.ts +8 -0
package/package.json
CHANGED
|
@@ -2,6 +2,11 @@ import { Text } from '../../Content/Text';
|
|
|
2
2
|
|
|
3
3
|
export type JsonLeafNodeProps = {
|
|
4
4
|
value: unknown;
|
|
5
|
+
/** When true, render `null` / `undefined` via Text with the monospace font.
|
|
6
|
+
* JsonTable sets this on recursive calls so leaves inside a table inherit
|
|
7
|
+
* the same font as the surrounding monospace cells (Text otherwise sets
|
|
8
|
+
* its own font-family and would break the inheritance). */
|
|
9
|
+
isMono?: boolean;
|
|
5
10
|
};
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -13,14 +18,15 @@ export type JsonLeafNodeProps = {
|
|
|
13
18
|
* placeholder until JsonTable grows specialized renderers for them.
|
|
14
19
|
*/
|
|
15
20
|
export const JsonLeafNode = (props: JsonLeafNodeProps) => {
|
|
16
|
-
const { value } = props;
|
|
21
|
+
const { value, isMono } = props;
|
|
22
|
+
const size = isMono ? 'small' : undefined;
|
|
17
23
|
|
|
18
24
|
if (value === null) {
|
|
19
|
-
return <Text isMuted>null</Text>;
|
|
25
|
+
return <Text isMuted isMono={isMono} size={size}>null</Text>;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
if (value === undefined) {
|
|
23
|
-
return <Text isMuted>undefined</Text>;
|
|
29
|
+
return <Text isMuted isMono={isMono} size={size}>undefined</Text>;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
32
|
if (typeof value === 'boolean') {
|
|
@@ -1,33 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
QuickTable,
|
|
3
|
+
QuickTableRow,
|
|
4
|
+
QuickTableCell,
|
|
5
|
+
QuickTableHeaderRow,
|
|
6
|
+
QuickTableHeaderCell,
|
|
7
|
+
} from '../../Tables/QuickTable';
|
|
2
8
|
import { JsonLeafNode } from './JsonLeafNode';
|
|
3
9
|
import { isPlainObject } from './utils';
|
|
4
10
|
import type { JsonTableProps } from './types';
|
|
11
|
+
import styles from './styles.module.css';
|
|
5
12
|
|
|
6
13
|
export const JsonTable = (props: JsonTableProps) => {
|
|
7
|
-
const { value, title } = props;
|
|
14
|
+
const { value, title, isNested } = props;
|
|
8
15
|
|
|
9
16
|
if (isPlainObject(value)) {
|
|
10
17
|
const entries = Object.entries(value);
|
|
11
18
|
|
|
12
|
-
|
|
13
|
-
<
|
|
19
|
+
const headerRow = title ? (
|
|
20
|
+
<QuickTableHeaderRow>
|
|
21
|
+
<QuickTableHeaderCell colSpan={2}>{title}</QuickTableHeaderCell>
|
|
22
|
+
</QuickTableHeaderRow>
|
|
23
|
+
) : undefined;
|
|
24
|
+
|
|
25
|
+
const table = (
|
|
26
|
+
<QuickTable headerRow={headerRow} hasColumnDividers hasOuterBorder={!isNested}>
|
|
14
27
|
{entries.map((entry) => {
|
|
15
28
|
const [key, child] = entry;
|
|
29
|
+
const childIsObject = isPlainObject(child);
|
|
16
30
|
|
|
17
31
|
return (
|
|
18
32
|
<QuickTableRow key={key}>
|
|
19
33
|
<QuickTableCell width={1}>{key}</QuickTableCell>
|
|
20
|
-
<QuickTableCell>
|
|
21
|
-
<JsonTable value={child} title={key} />
|
|
34
|
+
<QuickTableCell hasPadding={!childIsObject}>
|
|
35
|
+
<JsonTable value={child} title={key} isNested />
|
|
22
36
|
</QuickTableCell>
|
|
23
37
|
</QuickTableRow>
|
|
24
38
|
);
|
|
25
39
|
})}
|
|
26
40
|
</QuickTable>
|
|
27
41
|
);
|
|
42
|
+
|
|
43
|
+
return isNested ? table : <div className={styles.root}>{table}</div>;
|
|
28
44
|
}
|
|
29
45
|
|
|
30
|
-
return <JsonLeafNode value={value} />;
|
|
46
|
+
return <JsonLeafNode value={value} isMono={isNested} />;
|
|
31
47
|
};
|
|
32
48
|
|
|
33
49
|
export type { JsonTableProps };
|
|
@@ -6,8 +6,17 @@ export type JsonTableProps = {
|
|
|
6
6
|
/** Any value. JsonTable inspects shape and dispatches to a specialized
|
|
7
7
|
* renderer; primitives and unknown shapes fall back to JsonLeafNode. */
|
|
8
8
|
value: JsonValue;
|
|
9
|
-
/** Optional
|
|
10
|
-
* object. JsonTable also passes the parent key down as
|
|
11
|
-
* recursive call, so nested object-valued cells render a
|
|
9
|
+
/** Optional title rendered as a header row inside the table border when
|
|
10
|
+
* value is a plain object. JsonTable also passes the parent key down as
|
|
11
|
+
* `title` on each recursive call, so nested object-valued cells render a
|
|
12
|
+
* labeled table. */
|
|
12
13
|
title?: ReactNode;
|
|
14
|
+
/** @internal Set by JsonTable on every recursive call (i.e. when rendering
|
|
15
|
+
* a child entry of a parent table). Two effects: (1) on a nested object,
|
|
16
|
+
* suppresses the outer border so the inner table sits flush inside its
|
|
17
|
+
* parent cell — whose padding is also dropped at the parent level; (2) on
|
|
18
|
+
* a primitive leaf, signals JsonLeafNode to render `null` / `undefined`
|
|
19
|
+
* via Text with the monospace font so they inherit the surrounding font
|
|
20
|
+
* set by the JsonTable root. Not intended for external callers. */
|
|
21
|
+
isNested?: boolean;
|
|
13
22
|
};
|
|
@@ -25,10 +25,13 @@ const widthStyle = (
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export const QuickTableCell = (props: QuickTableCellProps) => {
|
|
28
|
-
const { children, width, align } = props;
|
|
28
|
+
const { children, width, align, hasPadding = true } = props;
|
|
29
29
|
|
|
30
30
|
return (
|
|
31
|
-
<td
|
|
31
|
+
<td
|
|
32
|
+
className={cx(styles.cell, alignClass(align), !hasPadding && styles.cellFlush)}
|
|
33
|
+
style={widthStyle(width)}
|
|
34
|
+
>
|
|
32
35
|
{children}
|
|
33
36
|
</td>
|
|
34
37
|
);
|
|
@@ -43,10 +46,14 @@ export const QuickTableRow = (props: QuickTableRowProps) => {
|
|
|
43
46
|
brandQuickTableType(QuickTableRow, 'QuickTableRow');
|
|
44
47
|
|
|
45
48
|
export const QuickTableHeaderCell = (props: QuickTableHeaderCellProps) => {
|
|
46
|
-
const { children, width, align } = props;
|
|
49
|
+
const { children, width, align, colSpan } = props;
|
|
47
50
|
|
|
48
51
|
return (
|
|
49
|
-
<th
|
|
52
|
+
<th
|
|
53
|
+
className={cx(styles.headerCell, alignClass(align))}
|
|
54
|
+
style={widthStyle(width)}
|
|
55
|
+
colSpan={colSpan}
|
|
56
|
+
>
|
|
50
57
|
{children}
|
|
51
58
|
</th>
|
|
52
59
|
);
|
|
@@ -61,14 +68,21 @@ export const QuickTableHeaderRow = (props: QuickTableHeaderRowProps) => {
|
|
|
61
68
|
brandQuickTableType(QuickTableHeaderRow, 'QuickTableHeaderRow');
|
|
62
69
|
|
|
63
70
|
export const QuickTable = (props: QuickTableProps) => {
|
|
64
|
-
const { children, headerCells, headerRow, title, hasColumnDividers } =
|
|
71
|
+
const { children, headerCells, headerRow, title, hasColumnDividers, hasOuterBorder = true } =
|
|
72
|
+
props;
|
|
65
73
|
|
|
66
74
|
const header =
|
|
67
75
|
headerRow ??
|
|
68
76
|
(headerCells ? <QuickTableHeaderRow>{headerCells}</QuickTableHeaderRow> : undefined);
|
|
69
77
|
|
|
70
78
|
return (
|
|
71
|
-
<table
|
|
79
|
+
<table
|
|
80
|
+
className={cx(
|
|
81
|
+
styles.table,
|
|
82
|
+
hasColumnDividers && styles.tableWithColumnDividers,
|
|
83
|
+
!hasOuterBorder && styles.tableFlush,
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
72
86
|
{title ? <caption className={styles.caption}>{title}</caption> : null}
|
|
73
87
|
{header ? <thead>{header}</thead> : null}
|
|
74
88
|
<tbody>{wrapList(children, QuickTableRow)}</tbody>
|
|
@@ -17,6 +17,9 @@ export type QuickTableProps = {
|
|
|
17
17
|
title?: ReactNode;
|
|
18
18
|
/** Draw vertical divider lines between columns. Default: false. */
|
|
19
19
|
hasColumnDividers?: boolean;
|
|
20
|
+
/** Draw the outer border around the table. Default: true. Set false when
|
|
21
|
+
* the table sits flush inside a parent cell that already provides a frame. */
|
|
22
|
+
hasOuterBorder?: boolean;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
export type QuickTableRowProps = {
|
|
@@ -27,6 +30,10 @@ export type QuickTableCellProps = {
|
|
|
27
30
|
children: ReactNode;
|
|
28
31
|
width?: string | number;
|
|
29
32
|
align?: QuickTableCellAlign;
|
|
33
|
+
/** Apply the cell's inner padding. Default: true. Set false when the cell's
|
|
34
|
+
* content is itself a bordered block (e.g. a nested table) that should sit
|
|
35
|
+
* flush with the cell edges. */
|
|
36
|
+
hasPadding?: boolean;
|
|
30
37
|
};
|
|
31
38
|
|
|
32
39
|
export type QuickTableHeaderRowProps = {
|
|
@@ -37,4 +44,5 @@ export type QuickTableHeaderCellProps = {
|
|
|
37
44
|
children: ReactNode;
|
|
38
45
|
width?: string | number;
|
|
39
46
|
align?: QuickTableCellAlign;
|
|
47
|
+
colSpan?: number;
|
|
40
48
|
};
|