explico 0.4.0 → 0.5.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/CHANGELOG.md +273 -1
- package/README.md +103 -8
- package/dist/compiler/astro.d.ts +9 -1
- package/dist/compiler/astro.js +182 -3
- package/dist/compiler/cli.d.ts +13 -0
- package/dist/compiler/cli.js +28 -4
- package/dist/compiler/collections.d.ts +3 -2
- package/dist/compiler/collections.js +28 -1
- package/dist/compiler/course-config.d.ts +58 -1
- package/dist/compiler/course-config.js +28 -1
- package/dist/compiler/exports/standalone-html.d.ts +34 -0
- package/dist/compiler/exports/standalone-html.js +803 -0
- package/dist/compiler/manifest.d.ts +90 -6
- package/dist/compiler/manifest.js +150 -17
- package/dist/compiler/resolution-report.d.ts +4 -0
- package/dist/reference/base-abbreviations.d.mts +30 -0
- package/dist/reference/base-abbreviations.mjs +60 -0
- package/dist/reference/base-operators.d.mts +15 -0
- package/dist/reference/base-operators.mjs +40 -0
- package/dist/reference/base-roman-labels.d.mts +35 -0
- package/dist/reference/base-roman-labels.mjs +43 -0
- package/dist/reference/consistency.d.ts +8 -2
- package/dist/reference/consistency.js +50 -3
- package/dist/reference/diagrams-validate.d.ts +21 -0
- package/dist/reference/diagrams-validate.js +13 -0
- package/dist/reference/equations.d.mts +10 -15
- package/dist/reference/equations.mjs +67 -14
- package/dist/reference/gate-abbreviations.d.ts +17 -0
- package/dist/reference/gate-abbreviations.js +64 -0
- package/dist/reference/gate-math.d.ts +28 -5
- package/dist/reference/gate-math.js +5 -2
- package/dist/reference/gate-prose-notation.d.ts +60 -0
- package/dist/reference/gate-prose-notation.js +125 -0
- package/dist/reference/keyed-float-validate.d.ts +5 -5
- package/dist/reference/keyed-jsx-floats.d.mts +7 -12
- package/dist/reference/keyed-jsx-floats.mjs +50 -25
- package/dist/reference/knowledge-checks-validate.d.ts +35 -0
- package/dist/reference/knowledge-checks-validate.js +78 -0
- package/dist/reference/knowledge-checks.d.mts +25 -0
- package/dist/reference/knowledge-checks.mjs +45 -0
- package/dist/reference/lab-math-scope.d.ts +9 -1
- package/dist/reference/lab-math-scope.js +32 -4
- package/dist/reference/math-glyphs.d.mts +30 -0
- package/dist/reference/math-glyphs.mjs +367 -0
- package/dist/reference/mdx-attributes.d.mts +13 -0
- package/dist/reference/mdx-attributes.mjs +38 -0
- package/dist/reference/mixed-content.d.ts +17 -0
- package/dist/reference/mixed-content.js +29 -0
- package/dist/reference/page-notation.d.ts +52 -0
- package/dist/reference/page-notation.js +171 -0
- package/dist/reference/raw-floats-validate.d.ts +18 -0
- package/dist/reference/raw-floats-validate.js +53 -0
- package/dist/reference/raw-floats.d.mts +18 -0
- package/dist/reference/raw-floats.mjs +129 -0
- package/dist/reference/rehype-heading-anchors.d.mts +1 -1
- package/dist/reference/rehype-heading-anchors.mjs +107 -1
- package/dist/reference/rehype-table-header-labels.d.mts +26 -0
- package/dist/reference/rehype-table-header-labels.mjs +152 -0
- package/dist/reference/remark-abbreviations.d.mts +7 -0
- package/dist/reference/remark-abbreviations.mjs +174 -0
- package/dist/reference/remark-memo.d.mts +16 -0
- package/dist/reference/remark-memo.mjs +339 -0
- package/dist/reference/remark-notation.d.mts +57 -9
- package/dist/reference/remark-notation.mjs +354 -42
- package/dist/reference/remark-short-note.d.mts +4 -0
- package/dist/reference/remark-short-note.mjs +237 -0
- package/dist/reference/types.d.ts +16 -1
- package/dist/reference/units-vocab.js +4 -0
- package/docs/VERSIONING.md +33 -4
- package/docs/authoring/README.md +8 -0
- package/docs/authoring/agents.md +17 -2
- package/docs/authoring/components.md +135 -0
- package/docs/authoring/migrating.md +92 -7
- package/docs/authoring/notation.md +560 -1
- package/docs/authoring/structure.md +120 -8
- package/docs/authoring/visualizations.md +36 -3
- package/package.json +5 -2
- package/src/compiler/astro.ts +208 -3
- package/src/compiler/cli.ts +29 -2
- package/src/compiler/collections.ts +45 -4
- package/src/compiler/course-config.ts +92 -0
- package/src/compiler/exports/standalone-html.ts +963 -0
- package/src/compiler/manifest.ts +268 -22
- package/src/components/HoverPanel.astro +45 -4
- package/src/components/abbreviation/AbbreviationGlossary.astro +70 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +127 -0
- package/src/components/assessments/AssessmentRunner.tsx +52 -17
- package/src/components/assessments/AssessmentSet.astro +98 -14
- package/src/components/assessments/RenderedContent.tsx +55 -0
- package/src/components/assessments/assessment-randomization.ts +16 -0
- package/src/components/diagram/Diagram.astro +444 -83
- package/src/components/disclosure/hover-preview.ts +202 -0
- package/src/components/disclosure/persisted-disclosure.ts +66 -0
- package/src/components/examples/CompactExamples.astro +2 -0
- package/src/components/figure/Figure.astro +279 -10
- package/src/components/memo/Memo.astro +453 -0
- package/src/components/memo/ShortNote.astro +223 -0
- package/src/components/notation/NotationFormula.astro +18 -1
- package/src/components/notation/NotationLayer.astro +105 -8
- package/src/components/notation/render-notation-math.ts +39 -2
- package/src/components/notation/safe-math-to-react.ts +50 -0
- package/src/components/reference/FloatRefLayer.astro +233 -15
- package/src/components/starlight/CollapsibleSections.astro +461 -0
- package/src/components/starlight/DiagramEnhancer.astro +385 -0
- package/src/components/starlight/HeadingAnchorEnhancer.astro +5 -17
- package/src/components/starlight/KeyedFloatEnhancer.astro +81 -3
- package/src/components/starlight/LayoutHeader.astro +50 -0
- package/src/components/starlight/LayoutSocialIcons.astro +41 -2
- package/src/components/starlight/LessonExportActions.astro +436 -0
- package/src/components/starlight/LessonFooter.astro +27 -2
- package/src/components/starlight/section-parts.ts +31 -0
- package/src/components/table/Table.astro +293 -7
- package/src/components/table/TableOverflowExpander.astro +489 -0
- package/src/content-config.ts +20 -0
- package/src/reference/base-abbreviations.mjs +60 -0
- package/src/reference/base-operators.mjs +40 -0
- package/src/reference/base-roman-labels.mjs +43 -0
- package/src/reference/consistency.ts +73 -2
- package/src/reference/diagrams-validate.ts +40 -0
- package/src/reference/equations.mjs +67 -14
- package/src/reference/gate-abbreviations.ts +128 -0
- package/src/reference/gate-math.ts +27 -7
- package/src/reference/gate-prose-notation.ts +224 -0
- package/src/reference/keyed-float-validate.ts +5 -5
- package/src/reference/keyed-jsx-floats.mjs +50 -25
- package/src/reference/knowledge-checks-validate.ts +130 -0
- package/src/reference/knowledge-checks.mjs +45 -0
- package/src/reference/lab-math-scope.ts +45 -3
- package/src/reference/math-glyphs.mjs +367 -0
- package/src/reference/mdx-attributes.mjs +38 -0
- package/src/reference/mixed-content.ts +69 -0
- package/src/reference/page-notation.ts +252 -0
- package/src/reference/raw-floats-validate.ts +103 -0
- package/src/reference/raw-floats.mjs +129 -0
- package/src/reference/rehype-heading-anchors.mjs +107 -1
- package/src/reference/rehype-table-header-labels.mjs +152 -0
- package/src/reference/remark-abbreviations.mjs +174 -0
- package/src/reference/remark-memo.mjs +339 -0
- package/src/reference/remark-notation.mjs +354 -42
- package/src/reference/remark-short-note.mjs +237 -0
- package/src/reference/types.ts +16 -0
- package/src/reference/units-vocab.ts +4 -0
- package/src/styles/global.css +996 -50
|
@@ -26,6 +26,10 @@ import { renderNotationFormula } from '../notation/render-notation-math';
|
|
|
26
26
|
import type { SafeMathNode as SafeMathNodeType } from '../notation/render-notation-math';
|
|
27
27
|
import SafeMathNode from '../notation/SafeMathNode.astro';
|
|
28
28
|
import type { GlyphScopeEntry } from '../../reference/gloss';
|
|
29
|
+
import {
|
|
30
|
+
notationKeysInMathNodes,
|
|
31
|
+
registerPageNotationDependencies,
|
|
32
|
+
} from '../../reference/page-notation';
|
|
29
33
|
|
|
30
34
|
export interface DiagramNode {
|
|
31
35
|
readonly id: string;
|
|
@@ -53,6 +57,19 @@ export interface Props {
|
|
|
53
57
|
/** Glyph scope `formula` resolves against — omit if no node uses `formula`. */
|
|
54
58
|
scope?: readonly GlyphScopeEntry[];
|
|
55
59
|
direction?: 'TB' | 'LR';
|
|
60
|
+
/** Computed by `remark-notation.mjs` for a top-level lesson diagram. */
|
|
61
|
+
number?: string;
|
|
62
|
+
/** Computed by `remark-notation.mjs` for a top-level lesson diagram. */
|
|
63
|
+
anchorId?: string;
|
|
64
|
+
/** Author-chosen state for a reader with nothing saved yet. Default: `true`. */
|
|
65
|
+
defaultOpen?: boolean;
|
|
66
|
+
/** Persist the reader's open/closed choice across visits. Default: `true`. */
|
|
67
|
+
rememberState?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Emit a build warning when the laid-out SVG is wider than this many pixels.
|
|
70
|
+
* Set `false` only when horizontal overflow is deliberate. Default: `800`.
|
|
71
|
+
*/
|
|
72
|
+
warnAboveWidth?: number | false;
|
|
56
73
|
/**
|
|
57
74
|
* Prose text alternative for the SVG. When omitted, the fallback is
|
|
58
75
|
* generated from the node labels and the edge chain — readable, but a
|
|
@@ -69,6 +86,11 @@ const {
|
|
|
69
86
|
scope = [],
|
|
70
87
|
direction = 'TB',
|
|
71
88
|
description,
|
|
89
|
+
number,
|
|
90
|
+
anchorId,
|
|
91
|
+
defaultOpen = true,
|
|
92
|
+
rememberState = true,
|
|
93
|
+
warnAboveWidth = 800,
|
|
72
94
|
} = Astro.props;
|
|
73
95
|
|
|
74
96
|
const idPattern = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
@@ -78,6 +100,17 @@ if (!idPattern.test(id)) {
|
|
|
78
100
|
if (nodes.length === 0) {
|
|
79
101
|
throw new Error(`Diagram "${id}" has no nodes.`);
|
|
80
102
|
}
|
|
103
|
+
if ((number && !anchorId) || (!number && anchorId)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Diagram "${id}" must receive both computed \`number\` and \`anchorId\`, or neither.`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (
|
|
109
|
+
warnAboveWidth !== false &&
|
|
110
|
+
(!Number.isFinite(warnAboveWidth) || warnAboveWidth <= 0)
|
|
111
|
+
) {
|
|
112
|
+
throw new Error(`Diagram "${id}" requires a positive \`warnAboveWidth\`.`);
|
|
113
|
+
}
|
|
81
114
|
|
|
82
115
|
interface RenderedNode extends DiagramNode {
|
|
83
116
|
readonly mathNodes?: readonly SafeMathNodeType[];
|
|
@@ -114,6 +147,15 @@ const rendered: RenderedNode[] = nodes.map((node) => {
|
|
|
114
147
|
return { ...node, mathNodes };
|
|
115
148
|
});
|
|
116
149
|
|
|
150
|
+
for (const node of rendered) {
|
|
151
|
+
if (!node.mathNodes) continue;
|
|
152
|
+
registerPageNotationDependencies(
|
|
153
|
+
Astro.locals,
|
|
154
|
+
notationKeysInMathNodes(node.mathNodes),
|
|
155
|
+
`Diagram "${id}" node "${node.id}" formula "${node.formula}"`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
117
159
|
const sized = rendered.map((node) => ({
|
|
118
160
|
node,
|
|
119
161
|
box:
|
|
@@ -134,6 +176,19 @@ const layout = layoutDiagram(
|
|
|
134
176
|
const nodeById = new Map(rendered.map((node) => [node.id, node]));
|
|
135
177
|
const laidOutById = new Map(layout.nodes.map((node) => [node.id, node]));
|
|
136
178
|
const markerId = `diagram-arrow-${id}`;
|
|
179
|
+
const legacyAnchorId = `diagram-${id}`;
|
|
180
|
+
const renderedAnchorId = anchorId ?? legacyAnchorId;
|
|
181
|
+
const viewportId = `${legacyAnchorId}-viewport`;
|
|
182
|
+
|
|
183
|
+
if (warnAboveWidth !== false && layout.width > warnAboveWidth) {
|
|
184
|
+
console.warn(
|
|
185
|
+
`[explico/Diagram] "${id}" lays out at ${layout.width}px wide, above the ` +
|
|
186
|
+
`${warnAboveWidth}px authoring threshold. It will scroll and can be expanded ` +
|
|
187
|
+
`by readers, but consider recreating the graph with direction="TB", shorter ` +
|
|
188
|
+
`labels, or explicit node sizes. Set warnAboveWidth={false} only when the ` +
|
|
189
|
+
`horizontal overflow is intentional.`,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
137
192
|
|
|
138
193
|
/** A node's human label for the text fallback — never the internal id. */
|
|
139
194
|
function fallbackLabel(nodeId: string): string {
|
|
@@ -148,100 +203,361 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
148
203
|
}
|
|
149
204
|
---
|
|
150
205
|
|
|
151
|
-
<figure
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
>
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
206
|
+
<figure
|
|
207
|
+
class="diagram"
|
|
208
|
+
id={renderedAnchorId}
|
|
209
|
+
aria-labelledby={`${id}-caption`}
|
|
210
|
+
data-dia-number={number}
|
|
211
|
+
data-dia-key={number ? id : undefined}
|
|
212
|
+
data-diagram-width={layout.width}
|
|
213
|
+
data-diagram-expandable
|
|
214
|
+
>
|
|
215
|
+
<div class="diagram__titlebar">
|
|
216
|
+
<details
|
|
217
|
+
class="diagram__details"
|
|
218
|
+
data-diagram-details
|
|
219
|
+
data-remember-state={String(rememberState)}
|
|
220
|
+
data-state={defaultOpen ? 'open' : 'closed'}
|
|
221
|
+
open={defaultOpen}
|
|
222
|
+
>
|
|
223
|
+
<summary class="diagram__summary" id={`${id}-caption`}>
|
|
224
|
+
{number && <span class="diagram__number">Diagram {number}</span>}
|
|
225
|
+
<span class="diagram__caption-text">{label}</span>
|
|
226
|
+
</summary>
|
|
227
|
+
<div class="diagram__body" data-diagram-body>
|
|
228
|
+
<div
|
|
229
|
+
class="diagram-stage"
|
|
230
|
+
id={renderedAnchorId === legacyAnchorId ? undefined : legacyAnchorId}
|
|
231
|
+
>
|
|
232
|
+
<div
|
|
233
|
+
id={viewportId}
|
|
234
|
+
class="diagram-scroll"
|
|
235
|
+
tabindex="0"
|
|
236
|
+
role="group"
|
|
237
|
+
aria-labelledby={`${id}-caption`}
|
|
238
|
+
>
|
|
239
|
+
<div
|
|
240
|
+
class="diagram-canvas"
|
|
241
|
+
style={`--diagram-print-ratio: ${layout.width} / ${layout.height}; width: ${layout.width}px; height: ${layout.height}px;`}
|
|
242
|
+
>
|
|
243
|
+
<svg
|
|
244
|
+
viewBox={`0 0 ${layout.width} ${layout.height}`}
|
|
245
|
+
width="100%"
|
|
246
|
+
height="100%"
|
|
247
|
+
>
|
|
248
|
+
<defs>
|
|
249
|
+
<marker
|
|
250
|
+
id={markerId}
|
|
251
|
+
viewBox="0 0 10 10"
|
|
252
|
+
refX="9"
|
|
253
|
+
refY="5"
|
|
254
|
+
markerWidth="7"
|
|
255
|
+
markerHeight="7"
|
|
256
|
+
orient="auto-start-reverse"
|
|
257
|
+
>
|
|
258
|
+
<path
|
|
259
|
+
d="M 0 0 L 10 5 L 0 10 z"
|
|
260
|
+
class="diagram-arrowhead"
|
|
261
|
+
/>
|
|
262
|
+
</marker>
|
|
263
|
+
</defs>
|
|
264
|
+
|
|
265
|
+
{
|
|
266
|
+
layout.edges.map((edge) => (
|
|
267
|
+
<path
|
|
268
|
+
d={pathFrom(edge.points)}
|
|
269
|
+
class="diagram-edge"
|
|
270
|
+
marker-end={`url(#${markerId})`}
|
|
271
|
+
/>
|
|
272
|
+
))
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
{
|
|
276
|
+
layout.nodes.map((position) => {
|
|
277
|
+
const node = nodeById.get(position.id)!;
|
|
278
|
+
return (
|
|
279
|
+
<g
|
|
280
|
+
transform={`translate(${position.x}, ${position.y})`}
|
|
281
|
+
class="diagram-node"
|
|
282
|
+
>
|
|
283
|
+
<rect
|
|
284
|
+
width={position.width}
|
|
285
|
+
height={position.height}
|
|
286
|
+
rx="8"
|
|
287
|
+
ry="8"
|
|
288
|
+
/>
|
|
289
|
+
<foreignObject
|
|
290
|
+
width={position.width}
|
|
291
|
+
height={position.height}
|
|
292
|
+
>
|
|
293
|
+
<div
|
|
294
|
+
xmlns="http://www.w3.org/1999/xhtml"
|
|
295
|
+
class="diagram-node-content"
|
|
296
|
+
>
|
|
297
|
+
{
|
|
298
|
+
node.text && (
|
|
299
|
+
<span class="diagram-node-text">{node.text}</span>
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
{
|
|
303
|
+
node.mathNodes && (
|
|
304
|
+
<span class="diagram-node-formula notation-math">
|
|
305
|
+
{node.mathNodes.map((mathNode) => (
|
|
306
|
+
<SafeMathNode node={mathNode} />
|
|
307
|
+
))}
|
|
308
|
+
</span>
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
</div>
|
|
312
|
+
</foreignObject>
|
|
313
|
+
</g>
|
|
314
|
+
);
|
|
315
|
+
})
|
|
316
|
+
}
|
|
317
|
+
</svg>
|
|
318
|
+
</div>
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
<details class="diagram-fallback">
|
|
323
|
+
<summary>Diagram description</summary>
|
|
324
|
+
{
|
|
325
|
+
description ? (
|
|
326
|
+
<p>{description}</p>
|
|
327
|
+
) : (
|
|
328
|
+
<Fragment>
|
|
329
|
+
<ol>
|
|
330
|
+
{rendered.map((node) => (
|
|
331
|
+
<li>{fallbackLabel(node.id)}</li>
|
|
332
|
+
))}
|
|
333
|
+
</ol>
|
|
334
|
+
{edges.length > 0 && (
|
|
335
|
+
<p class="diagram-fallback-flow">
|
|
336
|
+
{edges.map((edge, index) => (
|
|
337
|
+
<Fragment>
|
|
338
|
+
{index > 0 && '; '}
|
|
339
|
+
{fallbackLabel(edge.from)} → {fallbackLabel(edge.to)}
|
|
340
|
+
</Fragment>
|
|
196
341
|
))}
|
|
197
|
-
</
|
|
342
|
+
</p>
|
|
198
343
|
)}
|
|
199
|
-
</
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
</svg>
|
|
206
|
-
</div>
|
|
344
|
+
</Fragment>
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
</details>
|
|
348
|
+
</div>
|
|
349
|
+
</details>
|
|
207
350
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
351
|
+
<a
|
|
352
|
+
class="diagram__title-anchor"
|
|
353
|
+
href={`#${renderedAnchorId}`}
|
|
354
|
+
aria-label={`${number ? `Diagram ${number}: ` : ''}${label}`}
|
|
355
|
+
>
|
|
356
|
+
<svg
|
|
357
|
+
aria-hidden="true"
|
|
358
|
+
width="16"
|
|
359
|
+
height="16"
|
|
360
|
+
viewBox="0 0 24 24"
|
|
361
|
+
fill="currentColor"
|
|
362
|
+
><path
|
|
363
|
+
d="m12.11 15.39-3.88 3.88a2.52 2.52 0 0 1-3.5 0 2.47 2.47 0 0 1 0-3.5l3.88-3.88a1 1 0 1 0-1.42-1.42l-3.88 3.89a4.48 4.48 0 0 0 6.33 6.33l3.89-3.88a1 1 0 0 0-1.42-1.42m8.58-12.08a4.49 4.49 0 0 0-6.33 0l-3.89 3.88a1 1 0 1 0 1.42 1.42l3.88-3.88a2.52 2.52 0 0 1 3.5 0 2.47 2.47 0 0 1 0 3.5l-3.88 3.88a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l3.88-3.89a4.49 4.49 0 0 0 0-6.33M8.83 15.17a1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.92-4.92a1 1 0 1 0-1.42-1.42l-4.92 4.92a1 1 0 0 0 0 1.42"
|
|
364
|
+
></path></svg
|
|
365
|
+
>
|
|
366
|
+
</a>
|
|
367
|
+
|
|
368
|
+
<div class="diagram-toolbar" data-diagram-toolbar hidden>
|
|
369
|
+
<button
|
|
370
|
+
type="button"
|
|
371
|
+
class="diagram-expand-button"
|
|
372
|
+
data-diagram-expand
|
|
373
|
+
aria-controls={viewportId}
|
|
374
|
+
aria-expanded="false"
|
|
375
|
+
title="Expand diagram horizontally"
|
|
376
|
+
>
|
|
377
|
+
<svg aria-hidden="true" viewBox="0 0 24 24">
|
|
378
|
+
<path class="diagram-expand-icon" d="M3 12h18M8 7l-5 5 5 5M16 7l5 5-5 5" />
|
|
379
|
+
<path
|
|
380
|
+
class="diagram-shrink-icon"
|
|
381
|
+
d="M3 12h7M7 9l3 3-3 3M21 12h-7M17 9l-3 3 3 3"
|
|
382
|
+
/>
|
|
383
|
+
</svg>
|
|
384
|
+
<span class="sr-only">Expand {label}</span>
|
|
385
|
+
</button>
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
234
388
|
</figure>
|
|
235
389
|
|
|
236
390
|
<style>
|
|
237
391
|
@layer starlight.components {
|
|
238
392
|
.diagram {
|
|
393
|
+
position: relative;
|
|
239
394
|
margin: 1.5rem 0;
|
|
395
|
+
max-width: 100%;
|
|
396
|
+
contain: inline-size;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.diagram__titlebar {
|
|
400
|
+
position: relative;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.diagram__details {
|
|
404
|
+
border-inline-start: 0;
|
|
405
|
+
padding-inline-start: 0;
|
|
240
406
|
}
|
|
241
407
|
|
|
242
|
-
.
|
|
243
|
-
|
|
408
|
+
.diagram__summary {
|
|
409
|
+
position: relative;
|
|
410
|
+
min-height: 1.75rem;
|
|
411
|
+
padding-inline-end: 4rem;
|
|
244
412
|
font-weight: 600;
|
|
413
|
+
cursor: pointer;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.diagram__summary::before {
|
|
417
|
+
position: absolute;
|
|
418
|
+
top: 50%;
|
|
419
|
+
left: -1.35em;
|
|
420
|
+
margin: 0;
|
|
421
|
+
transform: translateY(-50%);
|
|
422
|
+
opacity: 0;
|
|
423
|
+
transition:
|
|
424
|
+
opacity 150ms ease 700ms,
|
|
425
|
+
transform 150ms ease;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.diagram__details[data-state='open'] > .diagram__summary::before {
|
|
429
|
+
transform: translateY(-50%) rotateZ(90deg);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.diagram__details[data-state='closed'] > .diagram__summary::before {
|
|
433
|
+
opacity: 1;
|
|
434
|
+
transition: none;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.diagram__summary:hover::before,
|
|
438
|
+
.diagram__summary:focus-visible::before {
|
|
439
|
+
opacity: 1;
|
|
440
|
+
transition: opacity 100ms ease;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.diagram__body {
|
|
444
|
+
overflow: hidden;
|
|
445
|
+
transition: max-height 220ms ease;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.diagram__number {
|
|
449
|
+
color: var(--sl-color-text-accent);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.diagram__caption-text::before {
|
|
453
|
+
content: ' — ';
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.diagram__summary > .diagram__caption-text:first-child::before {
|
|
457
|
+
content: none;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
.diagram__title-anchor {
|
|
461
|
+
position: absolute;
|
|
462
|
+
top: 0.1rem;
|
|
463
|
+
inset-inline-end: 0;
|
|
464
|
+
display: inline-flex;
|
|
465
|
+
width: 1.5rem;
|
|
466
|
+
height: 1.5rem;
|
|
467
|
+
align-items: center;
|
|
468
|
+
justify-content: center;
|
|
469
|
+
color: var(--sl-color-gray-3);
|
|
470
|
+
text-decoration: none;
|
|
471
|
+
opacity: 1;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
.diagram[data-diagram-overflow='true'] .diagram__title-anchor {
|
|
475
|
+
inset-inline-end: 2rem;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.diagram__title-anchor svg {
|
|
479
|
+
width: 0.9rem;
|
|
480
|
+
height: 0.9rem;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.diagram__title-anchor:hover,
|
|
484
|
+
.diagram__title-anchor:focus-visible {
|
|
485
|
+
color: var(--sl-color-text-accent);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.diagram__title-anchor:focus-visible {
|
|
489
|
+
outline: 2px solid var(--sl-color-accent);
|
|
490
|
+
outline-offset: 0.1rem;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
@media (hover: hover) {
|
|
494
|
+
.diagram__title-anchor {
|
|
495
|
+
opacity: 0;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.diagram__details:has(> .diagram__summary:hover) ~ .diagram__title-anchor,
|
|
499
|
+
.diagram__details:has(> .diagram__summary:focus-visible)
|
|
500
|
+
~ .diagram__title-anchor,
|
|
501
|
+
.diagram__title-anchor:hover,
|
|
502
|
+
.diagram__title-anchor:focus-visible {
|
|
503
|
+
opacity: 1;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.diagram-stage {
|
|
508
|
+
min-width: 0;
|
|
509
|
+
max-width: 100%;
|
|
510
|
+
overflow: hidden;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.diagram-toolbar {
|
|
514
|
+
position: absolute;
|
|
515
|
+
z-index: 2;
|
|
516
|
+
top: -0.25rem;
|
|
517
|
+
inset-inline-end: 0;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.diagram-toolbar[hidden] {
|
|
521
|
+
display: none;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.diagram-expand-button {
|
|
525
|
+
display: inline-flex;
|
|
526
|
+
width: 1.75rem;
|
|
527
|
+
height: 1.75rem;
|
|
528
|
+
margin: 0;
|
|
529
|
+
align-items: center;
|
|
530
|
+
justify-content: center;
|
|
531
|
+
color: var(--sl-color-gray-2);
|
|
532
|
+
border: 0;
|
|
533
|
+
border-radius: 0.25rem;
|
|
534
|
+
background: transparent;
|
|
535
|
+
cursor: pointer;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.diagram-expand-button svg {
|
|
539
|
+
width: 1.1rem;
|
|
540
|
+
height: 1.1rem;
|
|
541
|
+
fill: none;
|
|
542
|
+
stroke: currentColor;
|
|
543
|
+
stroke-width: 1.8;
|
|
544
|
+
stroke-linecap: round;
|
|
545
|
+
stroke-linejoin: round;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
.diagram-expand-button[aria-expanded='false'] .diagram-shrink-icon,
|
|
549
|
+
.diagram-expand-button[aria-expanded='true'] .diagram-expand-icon {
|
|
550
|
+
display: none;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
.diagram-expand-button:hover {
|
|
554
|
+
color: var(--sl-color-text);
|
|
555
|
+
background: var(--sl-color-accent-low);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.diagram-expand-button:focus-visible {
|
|
559
|
+
outline: 2px solid var(--sl-color-accent);
|
|
560
|
+
outline-offset: 1px;
|
|
245
561
|
}
|
|
246
562
|
|
|
247
563
|
/* A wide graph scrolls inside its own box rather than shrinking to
|
|
@@ -250,6 +566,10 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
250
566
|
that: a scrollable region a keyboard user cannot reach is unreachable
|
|
251
567
|
content, not just an awkward one. */
|
|
252
568
|
.diagram-scroll {
|
|
569
|
+
width: 100%;
|
|
570
|
+
min-width: 0;
|
|
571
|
+
max-width: 100%;
|
|
572
|
+
flex: 1 1 auto;
|
|
253
573
|
overflow-x: auto;
|
|
254
574
|
padding-block: 0.15rem;
|
|
255
575
|
}
|
|
@@ -259,11 +579,27 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
259
579
|
outline-offset: 2px;
|
|
260
580
|
}
|
|
261
581
|
|
|
262
|
-
.diagram svg {
|
|
582
|
+
.diagram-canvas > svg {
|
|
263
583
|
display: block;
|
|
584
|
+
/* Starlight globally constrains SVGs to the content width. That is safe
|
|
585
|
+
for an all-SVG illustration, but this diagram embeds HTML/KaTeX in
|
|
586
|
+
`foreignObject` nodes. WebKit on iOS can scale the SVG geometry while
|
|
587
|
+
leaving that HTML at its unscaled size, which puts formulas outside
|
|
588
|
+
their boxes. Keep the build-time dimensions and let the keyboard-
|
|
589
|
+
reachable wrapper above provide the intended horizontal scroll. */
|
|
590
|
+
max-width: none;
|
|
264
591
|
overflow: visible;
|
|
265
592
|
}
|
|
266
593
|
|
|
594
|
+
.diagram-canvas {
|
|
595
|
+
flex: none;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.diagram.dia-ref-highlight {
|
|
599
|
+
outline: 3px solid var(--sl-color-accent);
|
|
600
|
+
outline-offset: 0.25rem;
|
|
601
|
+
}
|
|
602
|
+
|
|
267
603
|
.diagram-node rect {
|
|
268
604
|
fill: var(--sl-color-gray-7);
|
|
269
605
|
stroke: var(--sl-color-gray-5);
|
|
@@ -313,5 +649,30 @@ function pathFrom(points: readonly { x: number; y: number }[]): string {
|
|
|
313
649
|
.diagram-fallback ol {
|
|
314
650
|
padding-inline-start: 1.25rem;
|
|
315
651
|
}
|
|
652
|
+
|
|
653
|
+
@media print {
|
|
654
|
+
.diagram-toolbar,
|
|
655
|
+
.diagram__title-anchor,
|
|
656
|
+
.diagram__summary::before {
|
|
657
|
+
display: none;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
.diagram__number {
|
|
661
|
+
color: inherit;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
.diagram__body {
|
|
665
|
+
display: block !important;
|
|
666
|
+
max-height: none !important;
|
|
667
|
+
overflow: visible !important;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
@media (prefers-reduced-motion: reduce) {
|
|
672
|
+
.diagram__summary::before,
|
|
673
|
+
.diagram__body {
|
|
674
|
+
transition: none;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
316
677
|
}
|
|
317
678
|
</style>
|