@conduction/docusaurus-preset 3.0.0 → 3.1.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/package.json
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <LeafCard /> + <LeafGrid />
|
|
3
|
+
*
|
|
4
|
+
* Metadata header for an Open Register leaf integration. Mirrors the
|
|
5
|
+
* registry descriptor (id, label, icon, group, requiredApp, storage)
|
|
6
|
+
* so every per-leaf docs page leads with the same compact summary —
|
|
7
|
+
* one card, six fields, no prose to skim. Used at the top of every
|
|
8
|
+
* docs/Integrations/{leaf}.md page in the openregister docs site.
|
|
9
|
+
*
|
|
10
|
+
* Used on:
|
|
11
|
+
* - /docs/Integrations/{leaf} (one <LeafCard />)
|
|
12
|
+
* - /docs/Integrations/leaf-system (a <LeafGrid /> of all 18+1)
|
|
13
|
+
*
|
|
14
|
+
* Brand:
|
|
15
|
+
* - Pointy-top hex carries the leaf's MDI icon (cobalt by default,
|
|
16
|
+
* orange for the one accent-leaf when grouped). Falls back to the
|
|
17
|
+
* `id` initial when no icon is given.
|
|
18
|
+
* - Status pill colours: green = backend-ready, amber = stub,
|
|
19
|
+
* cobalt = external (OpenConnector-routed), grey = built-in.
|
|
20
|
+
*
|
|
21
|
+
* Usage in MDX:
|
|
22
|
+
*
|
|
23
|
+
* import {LeafCard} from '@conduction/docusaurus-preset/components';
|
|
24
|
+
*
|
|
25
|
+
* <LeafCard
|
|
26
|
+
* id="calendar"
|
|
27
|
+
* label="Meetings"
|
|
28
|
+
* icon="Calendar"
|
|
29
|
+
* group="comms"
|
|
30
|
+
* requiredApp="calendar"
|
|
31
|
+
* storage="link-table"
|
|
32
|
+
* status="backend-ready" />
|
|
33
|
+
*
|
|
34
|
+
* <LeafGrid /> renders a responsive grid of LeafCard children for
|
|
35
|
+
* the overview page:
|
|
36
|
+
*
|
|
37
|
+
* <LeafGrid>
|
|
38
|
+
* <LeafCard id="calendar" ... />
|
|
39
|
+
* <LeafCard id="contacts" ... />
|
|
40
|
+
* </LeafGrid>
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import React from 'react';
|
|
44
|
+
import styles from './LeafCard.module.css';
|
|
45
|
+
|
|
46
|
+
const STATUS_LABELS = {
|
|
47
|
+
'backend-ready': 'Backend ready',
|
|
48
|
+
'stub': 'Provider stub',
|
|
49
|
+
'external': 'External (OpenConnector)',
|
|
50
|
+
'built-in': 'Built-in',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const GROUP_LABELS = {
|
|
54
|
+
'core': 'Core',
|
|
55
|
+
'comms': 'Communication',
|
|
56
|
+
'docs': 'Documents',
|
|
57
|
+
'workflow': 'Workflow',
|
|
58
|
+
'external': 'External',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const STORAGE_LABELS = {
|
|
62
|
+
'magic-column': 'Magic column',
|
|
63
|
+
'link-table': 'Link table',
|
|
64
|
+
'external': 'External (no local store)',
|
|
65
|
+
'query-time': 'Query-time (live)',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Render a single MDI icon glyph by name, with a graceful fallback
|
|
70
|
+
* to the first letter of the leaf id when the icon name is unknown.
|
|
71
|
+
* The docs site doesn't ship the full MDI set, so unknown icons fall
|
|
72
|
+
* back to a text initial rather than 404'ing on a missing asset.
|
|
73
|
+
*/
|
|
74
|
+
function LeafGlyph({icon, id}) {
|
|
75
|
+
if (icon) {
|
|
76
|
+
// Defer the actual icon rendering to the consuming docs site
|
|
77
|
+
// (which can swizzle this if it wires up vue-material-design-icons
|
|
78
|
+
// or any equivalent React icon pack). Default: render the icon
|
|
79
|
+
// name as a small uppercase tag so the page still reads.
|
|
80
|
+
return <span className={styles.iconText} aria-hidden="true">{icon.charAt(0)}</span>;
|
|
81
|
+
}
|
|
82
|
+
return <span className={styles.iconText} aria-hidden="true">{(id || '?').charAt(0).toUpperCase()}</span>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function LeafCard({
|
|
86
|
+
id,
|
|
87
|
+
label,
|
|
88
|
+
icon,
|
|
89
|
+
group,
|
|
90
|
+
requiredApp,
|
|
91
|
+
storage,
|
|
92
|
+
status,
|
|
93
|
+
href,
|
|
94
|
+
description,
|
|
95
|
+
className,
|
|
96
|
+
}) {
|
|
97
|
+
const statusLabel = STATUS_LABELS[status] || status;
|
|
98
|
+
const groupLabel = GROUP_LABELS[group] || group;
|
|
99
|
+
const storageLabel = STORAGE_LABELS[storage] || storage;
|
|
100
|
+
const composed = [styles.card, styles['status-' + (status || 'unknown')], className].filter(Boolean).join(' ');
|
|
101
|
+
|
|
102
|
+
const inner = (
|
|
103
|
+
<>
|
|
104
|
+
<div className={styles.head}>
|
|
105
|
+
<div className={styles.hex} aria-hidden="true">
|
|
106
|
+
<LeafGlyph icon={icon} id={id} />
|
|
107
|
+
</div>
|
|
108
|
+
<div className={styles.heading}>
|
|
109
|
+
<div className={styles.label}>{label}</div>
|
|
110
|
+
<code className={styles.id}>{id}</code>
|
|
111
|
+
</div>
|
|
112
|
+
{status && <span className={styles.statusPill}>{statusLabel}</span>}
|
|
113
|
+
</div>
|
|
114
|
+
{description && <p className={styles.description}>{description}</p>}
|
|
115
|
+
<dl className={styles.meta}>
|
|
116
|
+
{group && (
|
|
117
|
+
<>
|
|
118
|
+
<dt>Group</dt>
|
|
119
|
+
<dd>{groupLabel}</dd>
|
|
120
|
+
</>
|
|
121
|
+
)}
|
|
122
|
+
{requiredApp !== undefined && (
|
|
123
|
+
<>
|
|
124
|
+
<dt>Required app</dt>
|
|
125
|
+
<dd>{requiredApp ? <code>{requiredApp}</code> : <span className={styles.muted}>None (always available)</span>}</dd>
|
|
126
|
+
</>
|
|
127
|
+
)}
|
|
128
|
+
{storage && (
|
|
129
|
+
<>
|
|
130
|
+
<dt>Storage</dt>
|
|
131
|
+
<dd>{storageLabel}</dd>
|
|
132
|
+
</>
|
|
133
|
+
)}
|
|
134
|
+
{icon && (
|
|
135
|
+
<>
|
|
136
|
+
<dt>Icon</dt>
|
|
137
|
+
<dd><code>{icon}</code></dd>
|
|
138
|
+
</>
|
|
139
|
+
)}
|
|
140
|
+
</dl>
|
|
141
|
+
</>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
// Render as link when href is set so leaves on the overview grid
|
|
145
|
+
// navigate to their dedicated page on click.
|
|
146
|
+
if (href) {
|
|
147
|
+
return <a href={href} className={composed}>{inner}</a>;
|
|
148
|
+
}
|
|
149
|
+
return <div className={composed}>{inner}</div>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function LeafGrid({columns = 3, children, className}) {
|
|
153
|
+
const composed = [styles.grid, styles['grid-' + columns], className].filter(Boolean).join(' ');
|
|
154
|
+
return <div className={composed}>{children}</div>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default LeafCard;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/* LeafCard — per-leaf metadata header.
|
|
2
|
+
Pointy-top hex + label + status pill + meta grid. Sized for both
|
|
3
|
+
single-card placement at the top of a docs page and grid placement
|
|
4
|
+
on the overview. */
|
|
5
|
+
|
|
6
|
+
.card {
|
|
7
|
+
display: block;
|
|
8
|
+
background: white;
|
|
9
|
+
border: 1px solid var(--c-cobalt-100);
|
|
10
|
+
border-radius: var(--radius-md);
|
|
11
|
+
padding: var(--space-5);
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
color: inherit;
|
|
14
|
+
transition: border-color 120ms ease, transform 120ms ease;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
a.card:hover {
|
|
18
|
+
border-color: var(--c-cobalt-400);
|
|
19
|
+
transform: translateY(-1px);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.head {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: var(--space-4);
|
|
26
|
+
margin-bottom: var(--space-3);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.hex {
|
|
30
|
+
width: 40px;
|
|
31
|
+
height: 46px;
|
|
32
|
+
clip-path: var(--hex-pointy-top);
|
|
33
|
+
background: var(--c-cobalt-50);
|
|
34
|
+
color: var(--c-cobalt-700);
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
font-weight: 700;
|
|
40
|
+
font-size: 16px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.iconText {
|
|
44
|
+
display: inline-block;
|
|
45
|
+
font-weight: 700;
|
|
46
|
+
font-size: 18px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.heading {
|
|
50
|
+
flex: 1;
|
|
51
|
+
min-width: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.label {
|
|
55
|
+
font-size: 18px;
|
|
56
|
+
font-weight: 700;
|
|
57
|
+
color: var(--c-cobalt-900);
|
|
58
|
+
margin: 0;
|
|
59
|
+
line-height: 1.2;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.id {
|
|
63
|
+
display: inline-block;
|
|
64
|
+
font-size: 12px;
|
|
65
|
+
color: var(--c-cobalt-400);
|
|
66
|
+
font-family: var(--conduction-typography-font-family-code);
|
|
67
|
+
margin-top: 2px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.statusPill {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
font-size: 11px;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
text-transform: uppercase;
|
|
75
|
+
letter-spacing: 0.06em;
|
|
76
|
+
padding: 4px 10px;
|
|
77
|
+
border-radius: 999px;
|
|
78
|
+
flex-shrink: 0;
|
|
79
|
+
white-space: nowrap;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.status-backend-ready .statusPill {
|
|
83
|
+
background: var(--c-cobalt-50);
|
|
84
|
+
color: var(--c-cobalt-700);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.status-stub .statusPill {
|
|
88
|
+
background: var(--c-orange-50, #fff4e5);
|
|
89
|
+
color: var(--c-orange-knvb);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.status-external .statusPill {
|
|
93
|
+
background: var(--c-cobalt-100);
|
|
94
|
+
color: var(--c-cobalt-900);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.status-built-in .statusPill {
|
|
98
|
+
background: var(--c-cobalt-50);
|
|
99
|
+
color: var(--c-cobalt-700);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.description {
|
|
103
|
+
font-size: 14px;
|
|
104
|
+
color: var(--c-cobalt-700);
|
|
105
|
+
margin: 0 0 var(--space-4);
|
|
106
|
+
line-height: 1.55;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.meta {
|
|
110
|
+
display: grid;
|
|
111
|
+
grid-template-columns: max-content 1fr;
|
|
112
|
+
gap: 6px var(--space-4);
|
|
113
|
+
margin: 0;
|
|
114
|
+
font-size: 13px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.meta dt {
|
|
118
|
+
color: var(--c-cobalt-400);
|
|
119
|
+
font-weight: 500;
|
|
120
|
+
text-transform: uppercase;
|
|
121
|
+
letter-spacing: 0.06em;
|
|
122
|
+
font-size: 11px;
|
|
123
|
+
align-self: center;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.meta dd {
|
|
127
|
+
margin: 0;
|
|
128
|
+
color: var(--c-cobalt-900);
|
|
129
|
+
align-self: center;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.muted {
|
|
133
|
+
color: var(--c-cobalt-400);
|
|
134
|
+
font-style: italic;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Grid for the overview page. */
|
|
138
|
+
.grid {
|
|
139
|
+
display: grid;
|
|
140
|
+
gap: var(--space-5);
|
|
141
|
+
margin: var(--space-5) 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.grid-1 { grid-template-columns: 1fr; }
|
|
145
|
+
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
146
|
+
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
147
|
+
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
148
|
+
|
|
149
|
+
@media (max-width: 768px) {
|
|
150
|
+
.grid-2, .grid-3, .grid-4 {
|
|
151
|
+
grid-template-columns: 1fr;
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/components/index.js
CHANGED
|
@@ -63,6 +63,12 @@ export {default as GameModal} from './GameModal/GameModal.jsx';
|
|
|
63
63
|
framework-agnostic diagram set in @conduction/diagrams. Brand is
|
|
64
64
|
flat-hex only; the 3D prism wrapper was removed in v3.0.0. */
|
|
65
65
|
export {Hex, Platform, DomainTree, DiagramPipeline, SideBox, HoneycombBg, Pair, ArchFlow} from './Diagrams/Diagrams.jsx';
|
|
66
|
+
|
|
67
|
+
/* LeafCard — metadata header for an Open Register leaf integration.
|
|
68
|
+
<LeafGrid> renders a responsive grid of LeafCards for the overview
|
|
69
|
+
page; <LeafCard> on its own anchors the top of a per-leaf docs
|
|
70
|
+
page. See docs/Integrations/leaf-system.md for the worked use. */
|
|
71
|
+
export {default as LeafCard, LeafGrid} from './LeafCard/LeafCard.jsx';
|
|
66
72
|
export {default as ComposeBlock} from './ComposeBlock/ComposeBlock.jsx';
|
|
67
73
|
export {default as AppsGrid} from './AppsGrid/AppsGrid.jsx';
|
|
68
74
|
export {default as AppMock} from './AppMock/AppMock.jsx';
|
package/src/css/brand.css
CHANGED
|
@@ -310,3 +310,23 @@ a:not(.navbar__link):not(.footer__link-item):not(.button):hover {
|
|
|
310
310
|
color: var(--c-cobalt-700);
|
|
311
311
|
background: transparent;
|
|
312
312
|
}
|
|
313
|
+
|
|
314
|
+
/* ============================================================
|
|
315
|
+
Body grows with content.
|
|
316
|
+
|
|
317
|
+
Infima ships `html, body { height: 100% }`. With long pages the
|
|
318
|
+
body stops at one viewport while content overflows beneath it.
|
|
319
|
+
Anything past that height paints over the browser canvas, not
|
|
320
|
+
over body. On screens where the canvas is dark (Chrome on macOS
|
|
321
|
+
dark mode, Windows high-contrast), the canal-footer pattern is
|
|
322
|
+
preceded by a `#1B1B1D` band.
|
|
323
|
+
|
|
324
|
+
Swapping `height: 100%` for `min-height: 100vh` keeps short
|
|
325
|
+
pages looking the same and lets body cover the full document
|
|
326
|
+
on long pages. Site-level customCss can still override.
|
|
327
|
+
============================================================ */
|
|
328
|
+
html,
|
|
329
|
+
body {
|
|
330
|
+
height: auto;
|
|
331
|
+
min-height: 100vh;
|
|
332
|
+
}
|