@plannotator/pi-extension 0.19.12 → 0.19.14

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.
@@ -1,629 +0,0 @@
1
- # Extended Patterns
2
-
3
- Components that complement visual-explainer's toolkit. These use the same Plannotator theme tokens from `theme-override.md` and can be mixed freely with Nico's `.ve-card`, `.kpi-card`, `.pipeline` patterns.
4
-
5
- ## Timeline
6
-
7
- Vertical timeline showing phases or sequence — without time estimates. Shows ordering and dependencies, not duration.
8
-
9
- ```html
10
- <div class="timeline">
11
- <div class="timeline-item">
12
- <div class="timeline-label">Phase 1</div>
13
- <div class="timeline-dot-col">
14
- <div class="timeline-dot active"></div>
15
- <div class="timeline-line"></div>
16
- </div>
17
- <div class="timeline-content">
18
- <h4>Foundation</h4>
19
- <p>Set up the core infrastructure and initial integrations.</p>
20
- </div>
21
- </div>
22
- <!-- more items -->
23
- </div>
24
- ```
25
-
26
- ```css
27
- .timeline { display: flex; flex-direction: column; gap: 0; }
28
-
29
- .timeline-item {
30
- display: grid;
31
- grid-template-columns: 100px 28px 1fr;
32
- gap: 16px;
33
- min-height: 80px;
34
- }
35
-
36
- .timeline-label {
37
- font-family: var(--font-mono);
38
- font-size: 0.75rem;
39
- color: var(--muted-foreground);
40
- text-align: right;
41
- padding-top: 4px;
42
- }
43
-
44
- .timeline-dot-col {
45
- display: flex;
46
- flex-direction: column;
47
- align-items: center;
48
- }
49
-
50
- .timeline-dot {
51
- width: 14px;
52
- height: 14px;
53
- border-radius: 50%;
54
- background: var(--card);
55
- border: 3px solid var(--primary);
56
- flex-shrink: 0;
57
- }
58
-
59
- .timeline-dot.active { background: var(--primary); }
60
-
61
- .timeline-line {
62
- width: 2px;
63
- flex: 1;
64
- background: var(--border);
65
- }
66
-
67
- .timeline-content { padding-bottom: 24px; }
68
-
69
- .timeline-content h4 {
70
- font-family: var(--font-display);
71
- font-size: 1rem;
72
- font-weight: 500;
73
- margin-bottom: 4px;
74
- }
75
-
76
- .timeline-content p {
77
- font-size: 0.88rem;
78
- color: var(--muted-foreground);
79
- }
80
- ```
81
-
82
- The last timeline item should hide the line: `style="background: transparent"` on the `.timeline-line`.
83
-
84
- ## Code Blocks with Syntax Highlighting
85
-
86
- Dark-themed code panels showing key interfaces, schemas, or API signatures. Use sparingly — show the 5-10 lines that matter, not full files.
87
-
88
- ```html
89
- <div class="code-panel">
90
- <span class="code-file">src/api/handler.ts</span>
91
- <pre><code><span class="kw">interface</span> <span class="fn">Config</span> {
92
- <span class="fn">port</span>: <span class="kw">number</span>;
93
- <span class="fn">host</span>: <span class="kw">string</span>;
94
- }</code></pre>
95
- </div>
96
- ```
97
-
98
- ```css
99
- .code-panel {
100
- background: var(--code-bg);
101
- border: 1.5px solid var(--border);
102
- border-radius: var(--radius);
103
- padding: 20px 24px;
104
- overflow-x: auto;
105
- margin: 16px 0;
106
- }
107
-
108
- .code-file {
109
- font-family: var(--font-mono);
110
- font-size: 0.7rem;
111
- color: var(--muted-foreground);
112
- display: block;
113
- margin-bottom: 8px;
114
- }
115
-
116
- .code-panel pre {
117
- margin: 0;
118
- font-family: var(--font-mono);
119
- font-size: 0.85rem;
120
- line-height: 1.55;
121
- color: var(--foreground);
122
- white-space: pre-wrap;
123
- word-break: break-word;
124
- }
125
-
126
- .code-panel .kw { color: var(--primary); }
127
- .code-panel .fn { color: var(--accent); }
128
- .code-panel .str { color: var(--success); }
129
- .code-panel .cm { color: var(--muted-foreground); font-style: italic; }
130
- .code-panel .num { color: var(--warning); }
131
- ```
132
-
133
- ## Risk Table
134
-
135
- Severity-graded risk assessment with colored badges.
136
-
137
- ```html
138
- <div class="risk-grid">
139
- <div class="risk-row">
140
- <div class="risk-name">Database migration on live table</div>
141
- <div><span class="risk-badge risk-high">HIGH</span></div>
142
- <div class="risk-mitigation">Run during off-peak with online DDL</div>
143
- </div>
144
- </div>
145
- ```
146
-
147
- ```css
148
- .risk-grid {
149
- border: 1.5px solid var(--border);
150
- border-radius: var(--radius);
151
- overflow: hidden;
152
- }
153
-
154
- .risk-row {
155
- display: grid;
156
- grid-template-columns: 1fr auto 1.5fr;
157
- gap: 24px;
158
- padding: 16px 24px;
159
- align-items: center;
160
- border-bottom: 1px solid var(--border);
161
- }
162
-
163
- .risk-row:last-child { border-bottom: none; }
164
- .risk-name { font-weight: 500; }
165
- .risk-mitigation { font-size: 0.9rem; color: var(--muted-foreground); }
166
-
167
- .risk-badge {
168
- font-family: var(--font-mono);
169
- font-size: 0.65rem;
170
- font-weight: 600;
171
- padding: 2px 8px;
172
- border-radius: 4px;
173
- text-transform: uppercase;
174
- letter-spacing: 0.04em;
175
- }
176
-
177
- .risk-high {
178
- background: color-mix(in oklab, var(--destructive) 15%, transparent);
179
- color: var(--destructive);
180
- }
181
- .risk-med {
182
- background: color-mix(in oklab, var(--warning) 15%, transparent);
183
- color: var(--warning);
184
- }
185
- .risk-low {
186
- background: color-mix(in oklab, var(--success) 15%, transparent);
187
- color: var(--success);
188
- }
189
- ```
190
-
191
- ## Open Questions
192
-
193
- Callout cards for unresolved decisions. Each names who can answer.
194
-
195
- ```html
196
- <div class="question">
197
- <h3>Should we use WebSockets or SSE?</h3>
198
- <p>SSE is simpler but unidirectional. WebSockets add infrastructure complexity.</p>
199
- <span class="question-owner">Decide with: infrastructure team</span>
200
- </div>
201
- ```
202
-
203
- ```css
204
- .question {
205
- border-left: 3px solid var(--primary);
206
- padding: 16px 24px;
207
- margin: 16px 0;
208
- background: var(--card);
209
- border-radius: 0 var(--radius) var(--radius) 0;
210
- }
211
-
212
- .question h3 {
213
- font-family: var(--font-display);
214
- font-size: 1.05rem;
215
- font-weight: 500;
216
- margin-bottom: 4px;
217
- }
218
-
219
- .question p {
220
- font-size: 0.9rem;
221
- color: var(--muted-foreground);
222
- line-height: 1.55;
223
- }
224
-
225
- .question-owner {
226
- font-family: var(--font-mono);
227
- font-size: 0.72rem;
228
- color: var(--primary);
229
- font-weight: 500;
230
- display: block;
231
- margin-top: 8px;
232
- }
233
- ```
234
-
235
- ## Inline SVG Diagrams
236
-
237
- For architecture, data flow, and simple flowcharts where Mermaid is overkill (under 8 nodes, simple topology). These produce crisp, theme-aware vector diagrams drawn directly in the HTML. Use Mermaid for anything with complex edge routing (10+ nodes, many crossing connections).
238
-
239
- ### Container
240
-
241
- ```html
242
- <div class="svg-panel">
243
- <svg viewBox="0 0 720 280" xmlns="http://www.w3.org/2000/svg" style="width:100%">
244
- <!-- diagram content -->
245
- </svg>
246
- <span class="svg-caption">Request flow through the API gateway</span>
247
- </div>
248
- ```
249
-
250
- ```css
251
- .svg-panel {
252
- border: 1.5px solid var(--border);
253
- border-radius: var(--radius);
254
- padding: 24px;
255
- margin: 24px 0;
256
- background: var(--card);
257
- }
258
-
259
- .svg-caption {
260
- font-family: var(--font-mono);
261
- font-size: 0.72rem;
262
- color: var(--muted-foreground);
263
- display: block;
264
- margin-top: 8px;
265
- text-align: center;
266
- }
267
- ```
268
-
269
- ### Arrow markers
270
-
271
- Define in `<defs>`. Reference via `marker-end="url(#arrow)"`.
272
-
273
- ```svg
274
- <defs>
275
- <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
276
- markerWidth="7" markerHeight="7" orient="auto-start-reverse">
277
- <path d="M0,0 L10,5 L0,10 z" fill="var(--muted-foreground)"/>
278
- </marker>
279
- <marker id="arrow-primary" viewBox="0 0 10 10" refX="9" refY="5"
280
- markerWidth="7" markerHeight="7" orient="auto-start-reverse">
281
- <path d="M0,0 L10,5 L0,10 z" fill="var(--primary)"/>
282
- </marker>
283
- <marker id="arrow-success" viewBox="0 0 10 10" refX="9" refY="5"
284
- markerWidth="7" markerHeight="7" orient="auto-start-reverse">
285
- <path d="M0,0 L10,5 L0,10 z" fill="var(--success)"/>
286
- </marker>
287
- <marker id="arrow-destructive" viewBox="0 0 10 10" refX="9" refY="5"
288
- markerWidth="7" markerHeight="7" orient="auto-start-reverse">
289
- <path d="M0,0 L10,5 L0,10 z" fill="var(--destructive)"/>
290
- </marker>
291
- </defs>
292
- ```
293
-
294
- ### Box node
295
-
296
- ```svg
297
- <g transform="translate(100, 80)">
298
- <rect width="140" height="56" rx="10" fill="var(--card)"
299
- stroke="var(--border)" stroke-width="1.5"/>
300
- <text x="70" y="24" text-anchor="middle"
301
- font-family="var(--font-sans)" font-size="13" font-weight="600"
302
- fill="var(--foreground)">API Server</text>
303
- <text x="70" y="40" text-anchor="middle"
304
- font-family="var(--font-mono)" font-size="10.5"
305
- fill="var(--muted-foreground)">Express + middleware</text>
306
- </g>
307
- ```
308
-
309
- ### Highlighted box (new or hot-path component)
310
-
311
- ```svg
312
- <g transform="translate(100, 80)">
313
- <rect width="140" height="56" rx="10"
314
- fill="color-mix(in oklab, var(--primary) 8%, transparent)"
315
- stroke="var(--primary)" stroke-width="1.5"/>
316
- <text x="70" y="24" text-anchor="middle"
317
- font-family="var(--font-sans)" font-size="13" font-weight="600"
318
- fill="var(--foreground)">New Service</text>
319
- <text x="70" y="40" text-anchor="middle"
320
- font-family="var(--font-mono)" font-size="10.5"
321
- fill="var(--primary)">to be created</text>
322
- </g>
323
- ```
324
-
325
- ### Connecting arrows
326
-
327
- ```svg
328
- <!-- Horizontal -->
329
- <line x1="240" y1="108" x2="320" y2="108"
330
- stroke="var(--muted-foreground)" stroke-width="1.5"
331
- marker-end="url(#arrow)"/>
332
-
333
- <!-- Vertical -->
334
- <line x1="170" y1="136" x2="170" y2="200"
335
- stroke="var(--muted-foreground)" stroke-width="1.5"
336
- marker-end="url(#arrow)"/>
337
-
338
- <!-- Dashed (async, optional, or secondary path) -->
339
- <line x1="240" y1="108" x2="320" y2="108"
340
- stroke="var(--primary)" stroke-width="1.5"
341
- stroke-dasharray="5 4"
342
- marker-end="url(#arrow-primary)"/>
343
- ```
344
-
345
- ### Edge labels
346
-
347
- ```svg
348
- <text x="280" y="100" text-anchor="middle"
349
- font-family="var(--font-mono)" font-size="9.5"
350
- fill="var(--muted-foreground)">REST</text>
351
- ```
352
-
353
- ### Flowchart elements
354
-
355
- ```svg
356
- <!-- Decision diamond -->
357
- <path d="M310,262 L352,294 L310,326 L268,294 Z"
358
- fill="var(--card)" stroke="var(--border)" stroke-width="1.5"/>
359
- <text x="310" y="298" text-anchor="middle"
360
- font-family="var(--font-sans)" font-size="11" font-weight="500"
361
- fill="var(--foreground)">Valid?</text>
362
-
363
- <!-- Terminal / pill node -->
364
- <rect x="260" y="20" width="100" height="36" rx="18"
365
- fill="var(--card)" stroke="var(--border)" stroke-width="1.5"/>
366
-
367
- <!-- Success endpoint -->
368
- <rect x="260" y="400" width="100" height="36" rx="18"
369
- fill="color-mix(in oklab, var(--success) 12%, transparent)"
370
- stroke="var(--success)" stroke-width="1.5"/>
371
-
372
- <!-- Failure endpoint -->
373
- <rect x="100" y="400" width="100" height="36" rx="18"
374
- fill="color-mix(in oklab, var(--destructive) 12%, transparent)"
375
- stroke="var(--destructive)" stroke-width="1.5"/>
376
-
377
- <!-- Curved branch from decision to side -->
378
- <path d="M268,294 C200,294 160,294 160,240"
379
- fill="none" stroke="var(--destructive)" stroke-width="1.5"
380
- marker-end="url(#arrow-destructive)"/>
381
- ```
382
-
383
- ### Data flow (request/response)
384
-
385
- ```svg
386
- <!-- Request (solid) -->
387
- <line x1="140" y1="100" x2="280" y2="100"
388
- stroke="var(--muted-foreground)" stroke-width="1.5"
389
- marker-end="url(#arrow)"/>
390
- <text x="210" y="92" text-anchor="middle"
391
- font-family="var(--font-mono)" font-size="9.5"
392
- fill="var(--muted-foreground)">POST /api/plan</text>
393
-
394
- <!-- Response (dashed) -->
395
- <line x1="280" y1="116" x2="140" y2="116"
396
- stroke="var(--primary)" stroke-width="1.5" stroke-dasharray="5 4"
397
- marker-end="url(#arrow-primary)"/>
398
- <text x="210" y="132" text-anchor="middle"
399
- font-family="var(--font-mono)" font-size="9.5"
400
- fill="var(--primary)">{ plan, status }</text>
401
- ```
402
-
403
- ### Fan-out pattern
404
-
405
- ```svg
406
- <line x1="200" y1="100" x2="340" y2="60"
407
- stroke="var(--muted-foreground)" stroke-width="1.5" marker-end="url(#arrow)"/>
408
- <line x1="200" y1="100" x2="340" y2="100"
409
- stroke="var(--muted-foreground)" stroke-width="1.5" marker-end="url(#arrow)"/>
410
- <line x1="200" y1="100" x2="340" y2="140"
411
- stroke="var(--muted-foreground)" stroke-width="1.5" marker-end="url(#arrow)"/>
412
- ```
413
-
414
- ### Bar chart
415
-
416
- ```svg
417
- <svg viewBox="0 0 400 180" xmlns="http://www.w3.org/2000/svg"
418
- style="width:100%;max-width:400px">
419
- <!-- Gridlines -->
420
- <line x1="40" y1="20" x2="380" y2="20" stroke="var(--border)" stroke-width="1" opacity="0.5"/>
421
- <line x1="40" y1="60" x2="380" y2="60" stroke="var(--border)" stroke-width="1" opacity="0.5"/>
422
- <line x1="40" y1="100" x2="380" y2="100" stroke="var(--border)" stroke-width="1" opacity="0.5"/>
423
- <line x1="40" y1="140" x2="380" y2="140" stroke="var(--border)" stroke-width="1"/>
424
-
425
- <!-- Bars (muted default, primary for peak) -->
426
- <rect x="60" y="60" width="40" height="80" rx="4" fill="var(--muted)"/>
427
- <rect x="120" y="40" width="40" height="100" rx="4" fill="var(--primary)"/>
428
- <rect x="180" y="80" width="40" height="60" rx="4" fill="var(--muted)"/>
429
-
430
- <!-- Value labels above bars -->
431
- <text x="140" y="35" text-anchor="middle"
432
- font-family="var(--font-mono)" font-size="10" font-weight="600"
433
- fill="var(--primary)">25</text>
434
-
435
- <!-- X-axis labels -->
436
- <text x="80" y="158" text-anchor="middle"
437
- font-family="var(--font-mono)" font-size="9"
438
- fill="var(--muted-foreground)">Q1</text>
439
- </svg>
440
- ```
441
-
442
- ### Using CSS classes in SVG
443
-
444
- For cleaner markup, define reusable classes inside the SVG:
445
-
446
- ```svg
447
- <svg viewBox="0 0 720 280" xmlns="http://www.w3.org/2000/svg">
448
- <style>
449
- .box { fill: var(--card); stroke: var(--border); stroke-width: 1.5; }
450
- .new { fill: color-mix(in oklab, var(--primary) 8%, transparent);
451
- stroke: var(--primary); stroke-width: 1.5; }
452
- .title { font-family: var(--font-sans); font-size: 13px;
453
- font-weight: 600; fill: var(--foreground); }
454
- .sub { font-family: var(--font-mono); font-size: 10.5px;
455
- fill: var(--muted-foreground); }
456
- .conn { stroke: var(--muted-foreground); stroke-width: 1.5; }
457
- </style>
458
- </svg>
459
- ```
460
-
461
- ### Positioning rules
462
-
463
- - `viewBox` with fixed coordinates + `style="width:100%;max-width:720px"` for responsive scaling
464
- - Standard node: `120–160px` wide, `48–56px` tall
465
- - Minimum gap: `60px` horizontal, `40px` vertical
466
- - Arrow label offset: `8–12px` above the line
467
-
468
- ### Color roles in SVG
469
-
470
- | Element | Token |
471
- |---------|-------|
472
- | Box background | `var(--card)` |
473
- | Box stroke | `var(--border)` |
474
- | Highlighted box | `var(--primary)` stroke, `color-mix(in oklab, var(--primary) 8%, transparent)` fill |
475
- | Arrows / connectors | `var(--muted-foreground)` |
476
- | Title text | `var(--foreground)` |
477
- | Subtitle / labels | `var(--muted-foreground)` |
478
- | Success path | `var(--success)` |
479
- | Error path | `var(--destructive)` |
480
- | Warning | `var(--warning)` |
481
-
482
- ## Section Headers
483
-
484
- Numbered sections with display font headings:
485
-
486
- ```css
487
- .section-header {
488
- display: flex;
489
- align-items: baseline;
490
- gap: 14px;
491
- margin-bottom: 24px;
492
- padding-bottom: 8px;
493
- border-bottom: 1.5px solid var(--border);
494
- }
495
-
496
- .section-num {
497
- font-family: var(--font-mono);
498
- font-size: 0.75rem;
499
- font-weight: 600;
500
- color: var(--primary);
501
- }
502
-
503
- .section-header h2 {
504
- font-family: var(--font-display);
505
- font-size: 1.35rem;
506
- font-weight: 500;
507
- }
508
- ```
509
-
510
- ## Tag Chips
511
-
512
- Small inline labels for categorizing items:
513
-
514
- ```css
515
- .tag {
516
- font-family: var(--font-mono);
517
- font-size: 0.68rem;
518
- padding: 2px 8px;
519
- border-radius: 4px;
520
- background: var(--muted);
521
- color: var(--muted-foreground);
522
- }
523
-
524
- .tag-highlight {
525
- background: color-mix(in oklab, var(--primary) 12%, transparent);
526
- color: var(--primary);
527
- }
528
- ```
529
-
530
- ## Diff Rendering (for PR reviews)
531
-
532
- Use Pierre diffs via CDN for syntax-highlighted, theme-aware diff rendering. Pierre renders into shadow DOM (no style conflicts) and supports Plannotator theme tokens via CSS variable injection.
533
-
534
- ```html
535
- <script type="module">
536
- import { getSingularPatch, registerDiffsComponent } from 'https://cdn.jsdelivr.net/npm/@pierre/diffs@1.1.21/+esm';
537
-
538
- registerDiffsComponent();
539
-
540
- const patch = `--- a/src/handler.ts
541
- +++ b/src/handler.ts
542
- @@ -1,4 +1,6 @@
543
- import { Router } from 'express';
544
- +import { NotificationService } from './notifications';
545
- -import { legacyPoll } from './polling';
546
-
547
- export function createHandler() {`;
548
-
549
- const fileDiff = getSingularPatch(patch);
550
-
551
- const container = document.querySelector('diffs-container');
552
- container.fileDiff = fileDiff;
553
- container.options = {
554
- themeType: window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light',
555
- diffStyle: 'unified',
556
- diffIndicators: 'bars',
557
- lineDiffType: 'word-alt',
558
- unsafeCSS: `
559
- :host {
560
- --diffs-bg: var(--background);
561
- --diffs-fg: var(--foreground);
562
- --diffs-dark-bg: var(--background);
563
- --diffs-light-bg: var(--background);
564
- --diffs-dark: var(--foreground);
565
- --diffs-light: var(--foreground);
566
- border-radius: var(--radius);
567
- border: 1.5px solid var(--border);
568
- overflow: hidden;
569
- }
570
- `,
571
- };
572
- </script>
573
-
574
- <diffs-container></diffs-container>
575
- ```
576
-
577
- Pierre handles syntax highlighting (via Shiki), line numbers, add/del coloring, word-level diffs, and split/unified views automatically. The `unsafeCSS` option injects Plannotator theme tokens into the shadow DOM.
578
-
579
- For multiple diffs on one page, create one `<diffs-container>` per file and set `fileDiff` + `options` on each.
580
-
581
- ## Review Comment Bubbles (for PR reviews)
582
-
583
- Speech bubbles with severity-coded left borders.
584
-
585
- ```css
586
- .bubble {
587
- position: relative;
588
- background: var(--card);
589
- border: 1.5px solid var(--border);
590
- border-left-width: 4px;
591
- border-radius: 8px;
592
- padding: 12px 14px 12px 16px;
593
- max-width: 680px;
594
- }
595
-
596
- .bubble.blocking { border-left-color: var(--primary); }
597
- .bubble.nit { border-left-color: var(--border); }
598
- .bubble.suggestion { border-left-color: var(--success); }
599
-
600
- .bubble .severity {
601
- font-family: var(--font-mono);
602
- font-size: 0.65rem;
603
- font-weight: 700;
604
- text-transform: uppercase;
605
- letter-spacing: 0.06em;
606
- }
607
-
608
- .bubble.blocking .severity { color: var(--primary); }
609
- .bubble.nit .severity { color: var(--muted-foreground); }
610
- .bubble.suggestion .severity { color: var(--success); }
611
- ```
612
-
613
- ## File Badges (for PR reviews)
614
-
615
- ```css
616
- .file-badge {
617
- font-family: var(--font-mono);
618
- font-size: 0.62rem;
619
- font-weight: 700;
620
- text-transform: uppercase;
621
- letter-spacing: 0.04em;
622
- padding: 2px 6px;
623
- border-radius: 4px;
624
- }
625
-
626
- .file-badge.new { background: color-mix(in oklab, var(--success) 15%, transparent); color: var(--success); }
627
- .file-badge.mod { background: color-mix(in oklab, var(--warning) 15%, transparent); color: var(--warning); }
628
- .file-badge.del { background: color-mix(in oklab, var(--destructive) 15%, transparent); color: var(--destructive); }
629
- ```