adr-kit 0.9.0 → 0.11.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/README.md +23 -7
- package/README.zh.md +18 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +18 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +4 -3
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/graph.d.ts +3 -0
- package/dist/commands/graph.d.ts.map +1 -1
- package/dist/commands/graph.js +39 -6
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/supersede.js +1 -1
- package/dist/commands/supersede.js.map +1 -1
- package/dist/commands/tree.d.ts +1 -1
- package/dist/commands/tree.d.ts.map +1 -1
- package/dist/commands/tree.js +4 -1
- package/dist/commands/tree.js.map +1 -1
- package/dist/core/adr.d.ts +1 -0
- package/dist/core/adr.d.ts.map +1 -1
- package/dist/core/adr.js.map +1 -1
- package/dist/core/canvas-view.d.ts +21 -0
- package/dist/core/canvas-view.d.ts.map +1 -0
- package/dist/core/canvas-view.js +316 -0
- package/dist/core/canvas-view.js.map +1 -0
- package/dist/core/deliberation-html.d.ts +4 -0
- package/dist/core/deliberation-html.d.ts.map +1 -0
- package/dist/core/deliberation-html.js +153 -0
- package/dist/core/deliberation-html.js.map +1 -0
- package/dist/core/deliberation-view.d.ts +4 -0
- package/dist/core/deliberation-view.d.ts.map +1 -0
- package/dist/core/deliberation-view.js +341 -0
- package/dist/core/deliberation-view.js.map +1 -0
- package/dist/core/deliberation.d.ts +39 -7
- package/dist/core/deliberation.d.ts.map +1 -1
- package/dist/core/deliberation.js +175 -35
- package/dist/core/deliberation.js.map +1 -1
- package/dist/core/graph-html.d.ts +8 -0
- package/dist/core/graph-html.d.ts.map +1 -0
- package/dist/core/graph-html.js +299 -0
- package/dist/core/graph-html.js.map +1 -0
- package/dist/core/graph-view.d.ts +3 -0
- package/dist/core/graph-view.d.ts.map +1 -0
- package/dist/core/graph-view.js +80 -0
- package/dist/core/graph-view.js.map +1 -0
- package/dist/core/graph.d.ts +4 -1
- package/dist/core/graph.d.ts.map +1 -1
- package/dist/core/graph.js +11 -2
- package/dist/core/graph.js.map +1 -1
- package/dist/core/relation-focus.d.ts +4 -0
- package/dist/core/relation-focus.d.ts.map +1 -0
- package/dist/core/relation-focus.js +89 -0
- package/dist/core/relation-focus.js.map +1 -0
- package/dist/core/repository.d.ts.map +1 -1
- package/dist/core/repository.js +6 -2
- package/dist/core/repository.js.map +1 -1
- package/dist/core/share.d.ts +30 -0
- package/dist/core/share.d.ts.map +1 -0
- package/dist/core/share.js +420 -0
- package/dist/core/share.js.map +1 -0
- package/dist/core/templates.d.ts +10 -3
- package/dist/core/templates.d.ts.map +1 -1
- package/dist/core/templates.js +12 -2
- package/dist/core/templates.js.map +1 -1
- package/dist/core/tool-integrations.d.ts.map +1 -1
- package/dist/core/tool-integrations.js +55 -5
- package/dist/core/tool-integrations.js.map +1 -1
- package/dist/core/validate.d.ts +1 -1
- package/dist/core/validate.d.ts.map +1 -1
- package/dist/core/validate.js +56 -15
- package/dist/core/validate.js.map +1 -1
- package/dist/core/view-text.d.ts +21 -0
- package/dist/core/view-text.d.ts.map +1 -0
- package/dist/core/view-text.js +92 -0
- package/dist/core/view-text.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { escapeHtml } from './view-text.js';
|
|
2
|
+
import { GITHUB_MARK_PATH, SHARE_BUTTON_HTML, SHARE_WATERMARK } from './share.js';
|
|
3
|
+
/** Derived from the credit line, so the link and the image cannot drift apart. */
|
|
4
|
+
const REPOSITORY_URL = 'https://github.com/' + SHARE_WATERMARK;
|
|
5
|
+
/**
|
|
6
|
+
* The GitHub mark beside the wordmark — the same glyph the shared image
|
|
7
|
+
* credits with, filled rather than stroked because it is a logo here, and it
|
|
8
|
+
* inherits the link's colour so hover reaches it too.
|
|
9
|
+
*/
|
|
10
|
+
const BRAND_MARK = '<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false">'
|
|
11
|
+
+ '<path d="' + GITHUB_MARK_PATH + '" fill="currentColor"/></svg>';
|
|
12
|
+
/** Shared compact shell for both offline viewers. */
|
|
13
|
+
export const CANVAS_STYLE = String.raw `
|
|
14
|
+
:root { font-family: Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; color: #233c36; background: #f6f8f5; }
|
|
15
|
+
* { box-sizing: border-box; }
|
|
16
|
+
body { margin: 0; }
|
|
17
|
+
main { position: relative; }
|
|
18
|
+
button, summary { font: inherit; color: inherit; cursor: pointer; }
|
|
19
|
+
button:focus-visible, summary:focus-visible, main:focus-visible, a:focus-visible { outline: 2px solid #7750a5; outline-offset: -2px; }
|
|
20
|
+
.viewer-bar { position: relative; z-index: 5; display: flex; align-items: center; gap: 16px; padding: 8px 16px; min-height: 52px; background: #fff; border-bottom: 1px solid #e1e7e1; }
|
|
21
|
+
.viewer-heading { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
|
|
22
|
+
.viewer-brand { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 650; white-space: nowrap; padding-right: 12px; border-right: 1px solid #dce4dc; color: inherit; text-decoration: none; }
|
|
23
|
+
.viewer-brand svg { display: block; }
|
|
24
|
+
.viewer-brand:hover { color: #294d3e; text-decoration: underline; text-decoration-color: #a6bcae; text-underline-offset: 2px; }
|
|
25
|
+
.viewer-heading h1 { margin: 0; min-width: 0; font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
26
|
+
.viewer-count { flex: none; font-size: 12px; color: #64756c; }
|
|
27
|
+
.viewer-sep { flex: none; width: 1px; height: 18px; background: #dce4dc; }
|
|
28
|
+
.viewer-actions { display: flex; align-items: center; gap: 10px; flex: none; }
|
|
29
|
+
/* The controls are icon buttons: square, and close enough together to read as
|
|
30
|
+
one cluster while the count and the divider keep their distance. */
|
|
31
|
+
.viewer-tools { display: flex; align-items: center; gap: 4px; }
|
|
32
|
+
.viewer-bar button, .viewer-info > summary { border: 0; border-radius: 7px; background: transparent; padding: 7px; font-size: 12px; line-height: 20px; white-space: nowrap; }
|
|
33
|
+
.viewer-bar button:hover, .viewer-info > summary:hover, .viewer-info[open] > summary { background: #edf3ef; }
|
|
34
|
+
.viewer-info > summary { list-style: none; }
|
|
35
|
+
.viewer-info > summary::-webkit-details-marker { display: none; }
|
|
36
|
+
/* Toolbar icons sit on their own line: an inline SVG adds the font's descender
|
|
37
|
+
space below it, which lifts the icon out of line with its neighbour. This
|
|
38
|
+
belongs to the shared shell, or one view aligns and the other does not. */
|
|
39
|
+
.viewer-bar button svg, .viewer-bar summary svg { display: block; }
|
|
40
|
+
.viewer-panel { position: absolute; right: 12px; top: calc(100% + 8px); width: min(360px, calc(100vw - 24px)); max-height: calc(100vh - 120px); max-height: calc(100dvh - 120px); overflow: auto; overscroll-behavior: contain; padding: 20px; background: #fff; border: 1px solid #dce4dc; border-radius: 12px; box-shadow: 0 12px 36px #233c3620; font-size: 12px; line-height: 1.6; }
|
|
41
|
+
.viewer-panel h2 { margin: 0 0 10px; font-size: 15px; overflow-wrap: anywhere; }
|
|
42
|
+
.viewer-panel p { margin: 10px 0; color: #64756c; }
|
|
43
|
+
.viewer-stats { display: flex; gap: 8px 16px; flex-wrap: wrap; margin: 16px 0 0; }
|
|
44
|
+
.viewer-stats strong { margin-right: 4px; }
|
|
45
|
+
.canvas-dock { position: absolute; z-index: 4; left: 0; right: 0; bottom: 0; display: flex; align-items: flex-end; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 12px 16px; pointer-events: none; }
|
|
46
|
+
.canvas-dock > * { pointer-events: auto; }
|
|
47
|
+
/* Without the script there is no floating canvas: the dock sits at the end of the content. */
|
|
48
|
+
body:not(.interactive) main { padding-bottom: 84px; }
|
|
49
|
+
.canvas-legend { display: grid; gap: 6px; min-width: 0; max-width: min(620px, 100%); padding: 10px 12px; background: #ffffffe8; border: 1px solid #e1e7e1; border-radius: 10px; box-shadow: 0 4px 20px #294d3e0a; font-size: 11px; color: #55655c; }
|
|
50
|
+
.canvas-legend .legend { display: flex; flex-wrap: wrap; gap: 6px 16px; }
|
|
51
|
+
.canvas-legend .legend span { display: flex; align-items: center; gap: 8px; }
|
|
52
|
+
.viewer-panel .hint { border-top: 1px solid #e1e7e1; padding-top: 14px; margin: 16px 0 0; }
|
|
53
|
+
.controls { display: none; align-items: center; gap: 2px; padding: 5px; background: #fff; border: 1px solid #dce4dc; border-radius: 11px; box-shadow: 0 4px 20px #294d3e0a; }
|
|
54
|
+
.controls button { border: 0; background: none; font: inherit; color: inherit; cursor: pointer; padding: 6px 9px; border-radius: 7px; }
|
|
55
|
+
.controls button:hover { background: #edf3ef; }
|
|
56
|
+
.controls output { font: 11px monospace; min-width: 44px; text-align: center; }
|
|
57
|
+
.js-control { display: none; }
|
|
58
|
+
body.interactive { height: 100vh; height: 100dvh; display: flex; flex-direction: column; overflow: hidden; }
|
|
59
|
+
.interactive .viewer-bar { flex: none; }
|
|
60
|
+
.interactive main { flex: 1; min-width: 0; min-height: 0; overflow: hidden; touch-action: none; cursor: grab; user-select: none; }
|
|
61
|
+
.interactive #world { position: absolute; }
|
|
62
|
+
.interactive .js-control { display: block; }
|
|
63
|
+
.interactive .controls { display: flex; }
|
|
64
|
+
.interactive main.dragging { cursor: grabbing; }
|
|
65
|
+
@media (max-width: 760px) {
|
|
66
|
+
.viewer-bar { flex-wrap: wrap; gap: 4px 12px; padding: 6px 10px; }
|
|
67
|
+
.viewer-heading { flex-basis: 100%; min-height: 28px; }
|
|
68
|
+
.viewer-actions { width: 100%; justify-content: flex-end; }
|
|
69
|
+
.viewer-count { margin-right: auto; }
|
|
70
|
+
.viewer-panel { right: 10px; }
|
|
71
|
+
.canvas-legend { max-width: 100%; }
|
|
72
|
+
}
|
|
73
|
+
/* Below the count's breakpoint the row it sat on would hold two icons and
|
|
74
|
+
nothing else, so the bar goes back to one line and keeps its height for the
|
|
75
|
+
canvas. The brand gives up its room to the title, which needs it more. */
|
|
76
|
+
@media (max-width: 480px) {
|
|
77
|
+
.viewer-count, .viewer-sep, .viewer-brand { display: none; }
|
|
78
|
+
/* flex-basis 0, not auto: an auto basis measures the whole title, which no
|
|
79
|
+
row can hold, so the bar would wrap back into two lines. */
|
|
80
|
+
.viewer-heading { flex-basis: 0; }
|
|
81
|
+
.viewer-actions { width: auto; }
|
|
82
|
+
}
|
|
83
|
+
@media (pointer: coarse) {
|
|
84
|
+
.viewer-bar button, .viewer-info > summary { min-height: 44px; min-width: 44px; }
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
/**
|
|
88
|
+
* The Info disclosure is icon-only: the word carried no information of its
|
|
89
|
+
* own, and the glyph is unambiguous. The label keeps it accessible, and the
|
|
90
|
+
* separator sets the read-only count apart from the controls.
|
|
91
|
+
*/
|
|
92
|
+
const INFO_ICON = '<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">'
|
|
93
|
+
+ '<circle cx="8" cy="8" r="6.6" fill="none" stroke="currentColor" stroke-width="1.4"/>'
|
|
94
|
+
+ '<circle cx="8" cy="5.1" r=".95" fill="currentColor"/>'
|
|
95
|
+
+ '<path d="M8 7.4v4.2" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>';
|
|
96
|
+
/**
|
|
97
|
+
* The compact toolbar: brand, title, one headline count, and the controls —
|
|
98
|
+
* the Info disclosure and the Save-as-image camera, as one cluster. The canvas
|
|
99
|
+
* dock keeps the gesture controls. A statistic is listed only when its count is
|
|
100
|
+
* non-zero: a zero names something the view does not contain, which sends the
|
|
101
|
+
* reader looking for it.
|
|
102
|
+
*/
|
|
103
|
+
export function canvasHeaderHTML(title, stats, description) {
|
|
104
|
+
const listed = stats.filter(([, value]) => value !== 0);
|
|
105
|
+
const first = listed[0];
|
|
106
|
+
return '<header class="viewer-bar">'
|
|
107
|
+
+ '<div class="viewer-heading"><a class="viewer-brand" href="' + REPOSITORY_URL + '" target="_blank" rel="noopener noreferrer" title="' + SHARE_WATERMARK + ' on GitHub">' + BRAND_MARK + 'ADR Kit</a><h1>' + escapeHtml(title) + '</h1></div>'
|
|
108
|
+
+ '<div class="viewer-actions"><span class="viewer-count">' + (first ? first[1] + ' ' + escapeHtml(first[0]) : '') + '</span>'
|
|
109
|
+
+ '<span class="viewer-sep" aria-hidden="true"></span>'
|
|
110
|
+
+ '<div class="viewer-tools">'
|
|
111
|
+
+ '<details class="viewer-info"><summary aria-label="View information" title="View information">' + INFO_ICON + '</summary><section class="viewer-panel" aria-label="View information">'
|
|
112
|
+
+ '<h2>' + escapeHtml(title) + '</h2><p>' + escapeHtml(description) + '</p>'
|
|
113
|
+
+ '<div class="viewer-stats">' + listed.map(([label, value]) => '<span><strong>' + value + '</strong>' + escapeHtml(label) + '</span>').join('') + '</div>'
|
|
114
|
+
+ '<p id="instructions" class="hint">' + CANVAS_HINT + '</p>'
|
|
115
|
+
+ '</section></details>'
|
|
116
|
+
+ SHARE_BUTTON_HTML
|
|
117
|
+
+ '</div>'
|
|
118
|
+
+ '</div></header>';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The canvas dock: the legend over the bottom-left corner, the zoom cluster
|
|
122
|
+
* over the bottom-right. Both float above the canvas, so the header can stay
|
|
123
|
+
* compact without hiding what the picture means. A view with nothing to key
|
|
124
|
+
* draws no legend panel rather than an empty one.
|
|
125
|
+
*/
|
|
126
|
+
export function canvasDockHTML(legend, fitLabel) {
|
|
127
|
+
return '<div class="canvas-dock">'
|
|
128
|
+
+ (legend === '' ? '' : '<section class="canvas-legend" aria-label="Legend"><div class="legend">' + legend + '</div></section>')
|
|
129
|
+
+ canvasControlsHTML(fitLabel)
|
|
130
|
+
+ '</div>';
|
|
131
|
+
}
|
|
132
|
+
/** Shared pan/zoom controller for the offline HTML views. */
|
|
133
|
+
export const CANVAS_SCRIPT = String.raw `
|
|
134
|
+
|
|
135
|
+
(() => {
|
|
136
|
+
const viewport = document.getElementById('viewport');
|
|
137
|
+
const world = document.getElementById('world');
|
|
138
|
+
if (!viewport || !world) return;
|
|
139
|
+
document.body.classList.add('interactive');
|
|
140
|
+
const info = document.querySelector('.viewer-info');
|
|
141
|
+
document.addEventListener('keydown', event => {
|
|
142
|
+
if (event.key === 'Escape' && info && info.open) {
|
|
143
|
+
info.open = false;
|
|
144
|
+
info.querySelector('summary').focus();
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
document.addEventListener('pointerdown', event => {
|
|
148
|
+
if (info && info.open && !info.contains(event.target)) info.open = false;
|
|
149
|
+
});
|
|
150
|
+
let scale = 1, tx = 0, ty = 0, frame = 0;
|
|
151
|
+
|
|
152
|
+
function paint() {
|
|
153
|
+
world.style.transform = 'translate(' + tx + 'px,' + ty + 'px) scale(' + scale + ')';
|
|
154
|
+
const zoom = document.getElementById('zoom');
|
|
155
|
+
if (zoom) zoom.value = Math.round(scale * 100) + '%';
|
|
156
|
+
}
|
|
157
|
+
/** Overview: the whole diagram inside the viewport, behind the Fit control. */
|
|
158
|
+
function fit() {
|
|
159
|
+
const width = world.offsetWidth, height = world.offsetHeight;
|
|
160
|
+
if (!width || !height) return;
|
|
161
|
+
// Fit above the dock so no card hides behind the legend panel.
|
|
162
|
+
const dock = viewport.querySelector('.canvas-dock');
|
|
163
|
+
const padY = 48 + (dock ? dock.offsetHeight : 0);
|
|
164
|
+
scale = Math.max(.01, Math.min(1, (viewport.clientWidth - 48) / width, (viewport.clientHeight - padY) / height));
|
|
165
|
+
tx = (viewport.clientWidth - width * scale) / 2;
|
|
166
|
+
ty = (viewport.clientHeight - height * scale) / 2;
|
|
167
|
+
paint();
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The view a diagram opens in: readable first. Fit the width and never past
|
|
171
|
+
* 1:1, so a tall tree runs past the fold and pans instead of shrinking to a
|
|
172
|
+
* thumbnail whose text cannot be read. Fit is still the overview.
|
|
173
|
+
*/
|
|
174
|
+
function fitWidth() {
|
|
175
|
+
const width = world.offsetWidth, height = world.offsetHeight;
|
|
176
|
+
if (!width || !height) return;
|
|
177
|
+
scale = Math.max(.01, Math.min(1, (viewport.clientWidth - 48) / width));
|
|
178
|
+
tx = (viewport.clientWidth - width * scale) / 2;
|
|
179
|
+
const dock = viewport.querySelector('.canvas-dock');
|
|
180
|
+
const room = viewport.clientHeight - 48 - (dock ? dock.offsetHeight : 0);
|
|
181
|
+
ty = height * scale <= room ? (viewport.clientHeight - height * scale) / 2 : 24;
|
|
182
|
+
paint();
|
|
183
|
+
}
|
|
184
|
+
function zoomAt(factor, clientX, clientY) {
|
|
185
|
+
const next = Math.max(Math.min(scale, .05), Math.min(2, scale * factor));
|
|
186
|
+
const rect = viewport.getBoundingClientRect();
|
|
187
|
+
const x = clientX === undefined ? viewport.clientWidth / 2 : clientX - rect.left;
|
|
188
|
+
const y = clientY === undefined ? viewport.clientHeight / 2 : clientY - rect.top;
|
|
189
|
+
tx = x - (x - tx) * next / scale;
|
|
190
|
+
ty = y - (y - ty) * next / scale;
|
|
191
|
+
scale = next;
|
|
192
|
+
paint();
|
|
193
|
+
}
|
|
194
|
+
function zoom(factor) { zoomAt(factor); }
|
|
195
|
+
function addPan(dx, dy) { tx += dx; ty += dy; paint(); }
|
|
196
|
+
function relayout() { if (typeof window.__adrCanvasLayout === 'function') window.__adrCanvasLayout(); }
|
|
197
|
+
function schedule() {
|
|
198
|
+
if (frame) return;
|
|
199
|
+
frame = requestAnimationFrame(() => { frame = 0; relayout(); });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const plus = document.getElementById('plus');
|
|
203
|
+
const minus = document.getElementById('minus');
|
|
204
|
+
const fitButton = document.getElementById('fit');
|
|
205
|
+
const reset = document.getElementById('reset');
|
|
206
|
+
if (plus) plus.addEventListener('click', () => zoom(1.2));
|
|
207
|
+
if (minus) minus.addEventListener('click', () => zoom(1 / 1.2));
|
|
208
|
+
if (fitButton) fitButton.addEventListener('click', fit);
|
|
209
|
+
if (reset) reset.addEventListener('click', () => zoom(1 / scale));
|
|
210
|
+
|
|
211
|
+
let drag = null;
|
|
212
|
+
let panned = false;
|
|
213
|
+
// A press that moves pans; a press that stays is a click. The slop
|
|
214
|
+
// threshold is what lets links live inside the canvas: pointer capture
|
|
215
|
+
// would retarget their click, so capture waits until the gesture has
|
|
216
|
+
// committed to being a pan.
|
|
217
|
+
const CLICK_SLOP = 4;
|
|
218
|
+
viewport.addEventListener('pointerdown', event => {
|
|
219
|
+
if (event.button !== 0) return;
|
|
220
|
+
// Real controls keep their native press behavior: with pointer capture
|
|
221
|
+
// their click would land on the viewport and never reach them.
|
|
222
|
+
if (event.target.closest('button, summary, input, select, textarea, .controls, .canvas-legend')) return;
|
|
223
|
+
panned = false;
|
|
224
|
+
drag = { x: event.clientX, y: event.clientY, id: event.pointerId, moved: false };
|
|
225
|
+
});
|
|
226
|
+
viewport.addEventListener('pointermove', event => {
|
|
227
|
+
if (!drag || drag.id !== event.pointerId) return;
|
|
228
|
+
if (!drag.moved) {
|
|
229
|
+
if (Math.abs(event.clientX - drag.x) + Math.abs(event.clientY - drag.y) < CLICK_SLOP) return;
|
|
230
|
+
drag.moved = true;
|
|
231
|
+
viewport.setPointerCapture(event.pointerId);
|
|
232
|
+
viewport.classList.add('dragging');
|
|
233
|
+
}
|
|
234
|
+
tx += event.clientX - drag.x;
|
|
235
|
+
ty += event.clientY - drag.y;
|
|
236
|
+
drag.x = event.clientX;
|
|
237
|
+
drag.y = event.clientY;
|
|
238
|
+
paint();
|
|
239
|
+
});
|
|
240
|
+
viewport.addEventListener('pointerup', event => {
|
|
241
|
+
panned = drag !== null && drag.moved && drag.id === event.pointerId;
|
|
242
|
+
drag = null;
|
|
243
|
+
viewport.classList.remove('dragging');
|
|
244
|
+
});
|
|
245
|
+
for (const name of ['pointercancel', 'lostpointercapture']) {
|
|
246
|
+
viewport.addEventListener(name, () => { drag = null; viewport.classList.remove('dragging'); });
|
|
247
|
+
}
|
|
248
|
+
// The pan must not also open the link it started on, and a native link
|
|
249
|
+
// drag would cancel the pointer gesture outright.
|
|
250
|
+
viewport.addEventListener('click', event => {
|
|
251
|
+
if (!panned) return;
|
|
252
|
+
panned = false;
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
event.stopPropagation();
|
|
255
|
+
}, true);
|
|
256
|
+
viewport.addEventListener('dragstart', event => { if (drag) event.preventDefault(); });
|
|
257
|
+
// A trackpad pinch arrives as a ctrlKey wheel event; macOS also reports
|
|
258
|
+
// Command as metaKey. Either one zooms toward the pointer so the point under
|
|
259
|
+
// the cursor stays put (ADR 11), matching the on-screen hint. A plain wheel
|
|
260
|
+
// pans.
|
|
261
|
+
viewport.addEventListener('wheel', event => {
|
|
262
|
+
event.preventDefault();
|
|
263
|
+
if (event.ctrlKey || event.metaKey) {
|
|
264
|
+
zoomAt(Math.exp(-event.deltaY / 100), event.clientX, event.clientY);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
tx -= event.deltaX;
|
|
268
|
+
ty -= event.deltaY;
|
|
269
|
+
paint();
|
|
270
|
+
}, { passive: false });
|
|
271
|
+
viewport.addEventListener('keydown', event => {
|
|
272
|
+
if (event.target !== viewport) return;
|
|
273
|
+
const actions = {
|
|
274
|
+
ArrowLeft: () => { tx += 50; }, ArrowRight: () => { tx -= 50; },
|
|
275
|
+
ArrowUp: () => { ty += 50; }, ArrowDown: () => { ty -= 50; },
|
|
276
|
+
'+': () => zoom(1.2), '=': () => zoom(1.2), '-': () => zoom(1 / 1.2), '0': fit
|
|
277
|
+
};
|
|
278
|
+
if (actions[event.key]) { event.preventDefault(); actions[event.key](); paint(); }
|
|
279
|
+
});
|
|
280
|
+
viewport.addEventListener('focusin', event => {
|
|
281
|
+
if (!event.target.closest('.card, #world a')) return;
|
|
282
|
+
const target = event.target.getBoundingClientRect();
|
|
283
|
+
const view = viewport.getBoundingClientRect();
|
|
284
|
+
if (target.left < view.left || target.right > view.right || target.top < view.top || target.bottom > view.bottom) {
|
|
285
|
+
tx += view.left + view.width / 2 - (target.left + target.width / 2);
|
|
286
|
+
ty += view.top + view.height / 2 - (target.top + target.height / 2);
|
|
287
|
+
paint();
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
window.addEventListener('resize', () => { relayout(); fitWidth(); });
|
|
291
|
+
|
|
292
|
+
window.__adrCanvas = {
|
|
293
|
+
viewport, world,
|
|
294
|
+
get scale() { return scale; },
|
|
295
|
+
paint, fit, fitWidth, zoom, zoomAt, addPan, schedule, relayout
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// Open in the readable view, from the shared controller that owns it: the
|
|
299
|
+
// map has no layout step of its own, so without this it would sit unfitted.
|
|
300
|
+
// The tree's cards are laid out by the script that follows this one, which
|
|
301
|
+
// fits again once they are measured.
|
|
302
|
+
relayout();
|
|
303
|
+
fitWidth();
|
|
304
|
+
})();
|
|
305
|
+
`;
|
|
306
|
+
export const CANVAS_HINT = 'Drag anywhere or scroll to pan · Pinch or Ctrl/⌘ + scroll to zoom at the pointer · Arrow keys move · + / − zoom · 0 fits';
|
|
307
|
+
function canvasControlsHTML(fitLabel) {
|
|
308
|
+
return '<div class="controls js-control">'
|
|
309
|
+
+ '<button id="minus" aria-label="Zoom out">−</button>'
|
|
310
|
+
+ '<output id="zoom" aria-label="Zoom level">100%</output>'
|
|
311
|
+
+ '<button id="plus" aria-label="Zoom in">+</button>'
|
|
312
|
+
+ '<button id="fit" aria-label="' + escapeHtml(fitLabel) + '">Fit</button>'
|
|
313
|
+
+ '<button id="reset">1:1</button>'
|
|
314
|
+
+ '</div>';
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=canvas-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-view.js","sourceRoot":"","sources":["../../src/core/canvas-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DeliberationNode } from './deliberation.js';
|
|
2
|
+
/** Render semantic cards on the server; the embedded script only lays them out. */
|
|
3
|
+
export declare function renderCardTree(nodes: DeliberationNode[], title: string): string;
|
|
4
|
+
//# sourceMappingURL=deliberation-html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliberation-html.d.ts","sourceRoot":"","sources":["../../src/core/deliberation-html.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AA8C1D,mFAAmF;AACnF,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAyH/E"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { RELATION_STYLE, RELATION_SCRIPT } from './relation-focus.js';
|
|
2
|
+
import { isUnlockedQuestion } from './deliberation.js';
|
|
3
|
+
import { CANVAS_STYLE, CANVAS_SCRIPT, canvasHeaderHTML, canvasDockHTML } from './canvas-view.js';
|
|
4
|
+
import { TREE_STYLE, TREE_SCRIPT } from './deliberation-view.js';
|
|
5
|
+
import { SHARE_SCRIPT, SHARE_STYLE } from './share.js';
|
|
6
|
+
import { escapeHtml } from './view-text.js';
|
|
7
|
+
function kindOf(node) {
|
|
8
|
+
return node.type ?? (node.children.length > 0 ? 'question' : 'option');
|
|
9
|
+
}
|
|
10
|
+
/** Only option children can be answers; a settled follow-up is not an answer. */
|
|
11
|
+
function overridden(card) {
|
|
12
|
+
const chosen = card.options.filter(({ node }) => node.status === 'settled');
|
|
13
|
+
return card.kind === 'question' && chosen.length > 0
|
|
14
|
+
&& card.options.some(({ node }) => node.recommended)
|
|
15
|
+
&& !chosen.some(({ node }) => node.recommended);
|
|
16
|
+
}
|
|
17
|
+
function reason(node) {
|
|
18
|
+
return node.reason === undefined ? '' : `<p class="reason">${escapeHtml(node.reason)}</p>`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The exception states, with the gloss the legend gives each one. `settled` is
|
|
22
|
+
* absent on purpose: it is what a node is when nothing else is said, so a chip
|
|
23
|
+
* would repeat the same word on every card.
|
|
24
|
+
*/
|
|
25
|
+
const STATE_LEGEND = [
|
|
26
|
+
['open', 'unresolved'],
|
|
27
|
+
['rejected', 'not taken'],
|
|
28
|
+
['unrecorded', 'no state marker'],
|
|
29
|
+
];
|
|
30
|
+
/** Render semantic cards on the server; the embedded script only lays them out. */
|
|
31
|
+
export function renderCardTree(nodes, title) {
|
|
32
|
+
const cards = [];
|
|
33
|
+
let sequence = 0;
|
|
34
|
+
function collect(node, parent = '', anchor = '', depth = 0) {
|
|
35
|
+
const kind = depth === 0 && node.type === undefined ? 'root' : kindOf(node);
|
|
36
|
+
const card = { id: `n${++sequence}`, node, kind, parent, anchor, depth, options: [], children: [], unlocked: false };
|
|
37
|
+
cards.push(card);
|
|
38
|
+
for (const child of node.children) {
|
|
39
|
+
if (kind !== 'option' && kindOf(child) === 'option') {
|
|
40
|
+
const id = `n${++sequence}`;
|
|
41
|
+
card.options.push({ id, node: child });
|
|
42
|
+
for (const followup of child.children) {
|
|
43
|
+
card.children.push(collect(followup, card.id, id, depth + 1).id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
card.children.push(collect(child, card.id, '', depth + 1).id);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return card;
|
|
51
|
+
}
|
|
52
|
+
// A session that settles several decisions records them as sibling roots,
|
|
53
|
+
// which the canvas would draw as unrelated islands. Group them under one
|
|
54
|
+
// presentational card; recorded roots keep their kind, depth, and content.
|
|
55
|
+
// The card carries only its label: no heading, no count, no state.
|
|
56
|
+
const virtual = nodes.length > 1
|
|
57
|
+
? {
|
|
58
|
+
id: `n${++sequence}`,
|
|
59
|
+
node: { text: '', children: [] },
|
|
60
|
+
kind: 'virtual', parent: '', anchor: '', depth: 0, options: [], children: [], unlocked: false,
|
|
61
|
+
}
|
|
62
|
+
: undefined;
|
|
63
|
+
if (virtual !== undefined)
|
|
64
|
+
cards.push(virtual);
|
|
65
|
+
nodes.forEach((node) => {
|
|
66
|
+
const card = collect(node, virtual?.id ?? '');
|
|
67
|
+
virtual?.children.push(card.id);
|
|
68
|
+
});
|
|
69
|
+
// Whether each card's incoming edge is an unlocked one. The question is the
|
|
70
|
+
// outline's, not the drawing's: the node that raised this card is the option
|
|
71
|
+
// it anchors to, or the card it hangs off when it anchors to none. Asking it
|
|
72
|
+
// here lets the drawn edge and the legend read one answer.
|
|
73
|
+
const byId = new Map(cards.map((card) => [card.id, card]));
|
|
74
|
+
const optionNodes = new Map(cards.flatMap((card) => card.options.map(({ id, node }) => [id, node])));
|
|
75
|
+
for (const card of cards) {
|
|
76
|
+
const parent = byId.get(card.parent);
|
|
77
|
+
if (parent === undefined || card.kind === 'virtual')
|
|
78
|
+
continue;
|
|
79
|
+
const anchor = optionNodes.get(card.anchor);
|
|
80
|
+
card.unlocked = isUnlockedQuestion(card.node, anchor ?? parent.node, anchor === undefined && parent.kind === 'root');
|
|
81
|
+
}
|
|
82
|
+
let questionNumber = 0;
|
|
83
|
+
/** The states that actually draw a chip, so the legend keys only what it can point at. */
|
|
84
|
+
const chipped = new Set();
|
|
85
|
+
const markup = cards.map((card) => {
|
|
86
|
+
const { node, id, kind } = card;
|
|
87
|
+
const override = overridden(card);
|
|
88
|
+
const chosen = card.options.filter((option) => option.node.status === 'settled');
|
|
89
|
+
const other = card.options.filter((option) => option.node.status !== 'settled');
|
|
90
|
+
const status = node.status ?? 'unrecorded';
|
|
91
|
+
// Only an exception earns a chip; a settled node already reads as settled
|
|
92
|
+
// from its chosen answer, so the same word on every card would say nothing.
|
|
93
|
+
const chip = kind !== 'virtual' && status !== 'settled';
|
|
94
|
+
if (chip)
|
|
95
|
+
chipped.add(status);
|
|
96
|
+
const label = kind === 'question' ? `QUESTION ${String(++questionNumber).padStart(2, '0')}`
|
|
97
|
+
: kind === 'virtual' ? 'DELIBERATION' : kind.toUpperCase();
|
|
98
|
+
const stateChip = chip ? `<span class="state ${status}">${status}</span>` : '';
|
|
99
|
+
// A folded option writes its state as plain text, not as a chip, so it earns
|
|
100
|
+
// no legend key: the word is already readable and the pill is what needs one.
|
|
101
|
+
const optionMarkup = (option) => {
|
|
102
|
+
const selected = option.node.status === 'settled';
|
|
103
|
+
const state = option.node.status ?? 'unrecorded';
|
|
104
|
+
return `<div id="${option.id}" class="${selected ? 'answer' : 'alt'}" data-state="${state}">
|
|
105
|
+
<span class="badge">${selected ? '✓ Selected' : escapeHtml(state)}${option.node.recommended ? ' · Agent recommended' : ''}</span>
|
|
106
|
+
<p>${escapeHtml(option.node.text)}</p>${reason(option.node)}</div>`;
|
|
107
|
+
};
|
|
108
|
+
const heading = kind === 'virtual' ? '' : `<h2 id="${id}-title">${escapeHtml(node.text)}</h2>`;
|
|
109
|
+
const labelledBy = kind === 'virtual' ? '' : ` aria-labelledby="${id}-title"`;
|
|
110
|
+
const toggleLabel = kind === 'virtual' ? 'Toggle all decisions' : `Toggle follow-ups: ${escapeHtml(node.text)}`;
|
|
111
|
+
return `<article id="${id}" class="card ${kind}" data-parent="${card.parent}" data-anchor="${card.anchor}" data-state="${status}" data-unlocked="${card.unlocked}" style="--depth:${card.depth}"${labelledBy}${kind === 'virtual' ? '' : ' tabindex="0"'}>
|
|
112
|
+
<div class="cardhead"><div class="label"><span>${label}</span>${stateChip}</div>
|
|
113
|
+
${heading}${reason(node)}
|
|
114
|
+
${node.recommended ? '<p class="badge">Agent recommended</p>' : ''}
|
|
115
|
+
${override ? '<p class="override">Human override · recommendation not taken</p>' : ''}</div>
|
|
116
|
+
${chosen.map(optionMarkup).join('\n')}
|
|
117
|
+
${other.length === 0 ? '' : `<details class="alts"><summary>${other.length} other option${other.length === 1 ? '' : 's'}${override ? ' · includes recommendation' : ''}</summary>${other.map(optionMarkup).join('\n')}</details>`}
|
|
118
|
+
${card.children.length === 0 ? '' : `<button class="branch" aria-expanded="true" aria-controls="${card.children.join(' ')}" aria-label="${toggleLabel}">−</button>`}
|
|
119
|
+
</article>`;
|
|
120
|
+
}).join('\n');
|
|
121
|
+
const overrides = cards.filter(overridden).length;
|
|
122
|
+
const stats = [
|
|
123
|
+
['questions', questionNumber],
|
|
124
|
+
['options', cards.reduce((sum, card) => sum + card.options.length, 0)],
|
|
125
|
+
['overrides', overrides],
|
|
126
|
+
];
|
|
127
|
+
// The legend quotes what the picture draws: an entry for something no card
|
|
128
|
+
// shows sends the reader looking for it, so each one waits for its object.
|
|
129
|
+
// The edge keys carry a line sample in the stroke the view draws, because a
|
|
130
|
+
// dashed text dash looks like neither of the two edges it would be naming.
|
|
131
|
+
const legend = [
|
|
132
|
+
cards.some((card) => card.options.some(({ node }) => node.status === 'settled'))
|
|
133
|
+
? '<span data-share-selector=".card:not([hidden]) .answer">✓ Selected answer</span>' : '',
|
|
134
|
+
cards.some((card) => card.parent !== '') ? '<span data-share-selector="#edges path[data-unlocked=false]"><i class="edge-key"></i>Raised by</span>' : '',
|
|
135
|
+
cards.some((card) => card.unlocked) ? '<span data-share-selector="#edges path[data-unlocked=true]"><i class="edge-key unlocked"></i>Unlocked question</span>' : '',
|
|
136
|
+
overrides === 0 ? '' : '<span class="override-key" data-share-selector=".card:not([hidden]) .override">● Human override</span>',
|
|
137
|
+
...STATE_LEGEND
|
|
138
|
+
.filter(([state]) => chipped.has(state))
|
|
139
|
+
.map(([state, gloss]) => `<span data-share-selector=".card:not([hidden]) .cardhead .state.${state}"><span class="state ${state}">${state}</span>${gloss}</span>`),
|
|
140
|
+
].filter(Boolean).join('');
|
|
141
|
+
return `<!doctype html>
|
|
142
|
+
<html lang="en">
|
|
143
|
+
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
144
|
+
<title>${escapeHtml(title)} — deliberation tree</title><style>${TREE_STYLE}${CANVAS_STYLE}${SHARE_STYLE}${RELATION_STYLE}</style></head>
|
|
145
|
+
<body>
|
|
146
|
+
${canvasHeaderHTML(title, stats, 'Hover or focus a card to trace its ancestors and follow-ups. Escape clears the highlight.')}
|
|
147
|
+
<main id="viewport" tabindex="0" aria-label="Decision tree" aria-describedby="instructions"><div id="world"><svg id="edges" aria-hidden="true"></svg><div id="cards">${markup}</div></div>
|
|
148
|
+
${canvasDockHTML(legend, 'Fit tree')}</main>
|
|
149
|
+
<noscript><p class="no-script">JavaScript is disabled. All cards are shown in outline order; expand other options to read their reasons.</p></noscript>
|
|
150
|
+
<script>${CANVAS_SCRIPT}${SHARE_SCRIPT}${TREE_SCRIPT}${RELATION_SCRIPT}</script>
|
|
151
|
+
</body></html>\n`;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=deliberation-html.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliberation-html.js","sourceRoot":"","sources":["../../src/core/deliberation-html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjG,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAc5C,SAAS,MAAM,CAAC,IAAsB;IACpC,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AACzE,CAAC;AAED,iFAAiF;AACjF,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IAC5E,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;WAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;WACjD,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,MAAM,CAAC,IAAsB;IACpC,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC7F,CAAC;AAED;;;;GAIG;AACH,MAAM,YAAY,GAA4B;IAC5C,CAAC,MAAM,EAAE,YAAY,CAAC;IACtB,CAAC,UAAU,EAAE,WAAW,CAAC;IACzB,CAAC,YAAY,EAAE,iBAAiB,CAAC;CAClC,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,cAAc,CAAC,KAAyB,EAAE,KAAa;IACrE,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,SAAS,OAAO,CAAC,IAAsB,EAAE,MAAM,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC;QAC1E,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAS,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC3H,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,IAAI,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACpD,MAAM,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACvC,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACtC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,mEAAmE;IACnE,MAAM,OAAO,GAAqB,KAAK,CAAC,MAAM,GAAG,CAAC;QAChD,CAAC,CAAC;YACE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACpB,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;YAChC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK;SAC9F;QACH,CAAC,CAAC,SAAS,CAAC;IACd,IAAI,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IACH,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,2DAA2D;IAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAU,CAAC,CAAC,CAAC,CAAC;IAC9G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QAC9D,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG,kBAAkB,CAChC,IAAI,CAAC,IAAI,EACT,MAAM,IAAI,MAAM,CAAC,IAAI,EACrB,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAC/C,CAAC;IACJ,CAAC;IACD,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,0FAA0F;IAC1F,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC;QAC3C,0EAA0E;QAC1E,4EAA4E;QAC5E,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,CAAC;QACxD,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;YACzF,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,sBAAsB,MAAM,KAAK,MAAM,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,6EAA6E;QAC7E,8EAA8E;QAC9E,MAAM,YAAY,GAAG,CAAC,MAA+B,EAAU,EAAE;YAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC;YACjD,OAAO,YAAY,MAAM,CAAC,EAAE,YAAY,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,iBAAiB,KAAK;8BACjE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE;aACpH,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;QACxE,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,WAAW,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAC/F,MAAM,UAAU,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,EAAE,SAAS,CAAC;QAC9E,MAAM,WAAW,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,sBAAsB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChH,OAAO,gBAAgB,EAAE,iBAAiB,IAAI,kBAAkB,IAAI,CAAC,MAAM,kBAAkB,IAAI,CAAC,MAAM,iBAAiB,MAAM,oBAAoB,IAAI,CAAC,QAAQ,oBAAoB,IAAI,CAAC,KAAK,IAAI,UAAU,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe;uDACrM,KAAK,UAAU,SAAS;QACvE,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,EAAE;QAChE,QAAQ,CAAC,CAAC,CAAC,mEAAmE,CAAC,CAAC,CAAC,EAAE;QACnF,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kCAAkC,KAAK,CAAC,MAAM,gBAAgB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,EAAE,aAAa,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY;QAC/N,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,8DAA8D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,WAAW,cAAc;eAC1J,CAAC;IACd,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAClD,MAAM,KAAK,GAA4B;QACrC,CAAC,WAAW,EAAE,cAAc,CAAC;QAC7B,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC,WAAW,EAAE,SAAS,CAAC;KACzB,CAAC;IACF,2EAA2E;IAC3E,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,MAAM,GAAG;QACb,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;YAC9E,CAAC,CAAC,kFAAkF,CAAC,CAAC,CAAC,EAAE;QAC3F,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,uGAAuG,CAAC,CAAC,CAAC,EAAE;QACvJ,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,uHAAuH,CAAC,CAAC,CAAC,EAAE;QAClK,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,wGAAwG;QAC/H,GAAG,YAAY;aACZ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;aACvC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,mEAAmE,KAAK,wBAAwB,KAAK,KAAK,KAAK,UAAU,KAAK,SAAS,CAAC;KACpK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,OAAO;;;SAGA,UAAU,CAAC,KAAK,CAAC,sCAAsC,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc;;EAEtH,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,2FAA2F,CAAC;uKAC0C,MAAM;EAC3K,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC;;UAE1B,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe;iBACrD,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliberation-view.d.ts","sourceRoot":"","sources":["../../src/core/deliberation-view.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,eAAO,MAAM,UAAU,QA4NtB,CAAC;AAIF,eAAO,MAAM,WAAW,QAmHvB,CAAC"}
|