@issuegraph/editor 0.24.0 → 0.26.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.
Files changed (49) hide show
  1. package/README.md +6 -2
  2. package/dist/index.d.ts +2 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.js.map +1 -1
  6. package/dist/overlay/render.d.ts.map +1 -1
  7. package/dist/overlay/render.js +18 -2
  8. package/dist/overlay/render.js.map +1 -1
  9. package/dist/reevaluate/styles.d.ts +7 -1
  10. package/dist/reevaluate/styles.d.ts.map +1 -1
  11. package/dist/reevaluate/styles.js +32 -11
  12. package/dist/reevaluate/styles.js.map +1 -1
  13. package/dist/scale/render.d.ts +5 -1
  14. package/dist/scale/render.d.ts.map +1 -1
  15. package/dist/scale/render.js +19 -2
  16. package/dist/scale/render.js.map +1 -1
  17. package/dist/workspace/host.d.ts +33 -2
  18. package/dist/workspace/host.d.ts.map +1 -1
  19. package/dist/workspace/host.js +64 -14
  20. package/dist/workspace/host.js.map +1 -1
  21. package/dist/workspace/inspector.d.ts +9 -0
  22. package/dist/workspace/inspector.d.ts.map +1 -1
  23. package/dist/workspace/inspector.js +16 -0
  24. package/dist/workspace/inspector.js.map +1 -1
  25. package/dist/workspace/mount.d.ts +17 -3
  26. package/dist/workspace/mount.d.ts.map +1 -1
  27. package/dist/workspace/mount.js +150 -30
  28. package/dist/workspace/mount.js.map +1 -1
  29. package/dist/workspace/narrow.d.ts +38 -0
  30. package/dist/workspace/narrow.d.ts.map +1 -0
  31. package/dist/workspace/narrow.js +48 -0
  32. package/dist/workspace/narrow.js.map +1 -0
  33. package/dist/workspace/related.d.ts +65 -0
  34. package/dist/workspace/related.d.ts.map +1 -0
  35. package/dist/workspace/related.js +105 -0
  36. package/dist/workspace/related.js.map +1 -0
  37. package/dist/workspace/render.d.ts +102 -19
  38. package/dist/workspace/render.d.ts.map +1 -1
  39. package/dist/workspace/render.js +211 -29
  40. package/dist/workspace/render.js.map +1 -1
  41. package/dist/workspace/selection.d.ts +44 -3
  42. package/dist/workspace/selection.d.ts.map +1 -1
  43. package/dist/workspace/selection.js +58 -0
  44. package/dist/workspace/selection.js.map +1 -1
  45. package/dist/workspace/styles.d.ts +1 -1
  46. package/dist/workspace/styles.d.ts.map +1 -1
  47. package/dist/workspace/styles.js +265 -8
  48. package/dist/workspace/styles.js.map +1 -1
  49. package/package.json +3 -3
@@ -32,14 +32,15 @@
32
32
  * clean — which is the audit failing silently on exactly the rows where an
33
33
  * encoding error is hardest to see.
34
34
  *
35
- * ## The zone frames, and the one place a tag is written here
35
+ * ## The zone frames, and the one place markup is joined here
36
36
  *
37
37
  * Two of the four zones hand back a STRING rather than a spec — the ladder's
38
38
  * chrome and the audit header — so the frames are assembled by concatenation,
39
39
  * as `renderScaleLadder` already assembles its own canvas and chrome. What
40
- * makes that safe is not care: {@link ZONES} is a closed union of literals, so
41
- * no caller value can reach an attribute here at all, and `zones.test.ts` pins
42
- * it. Everything with a dynamic value in it goes through `renderMarkup`.
40
+ * makes that safe is not care: a frame's own opening tag carries the caller's
41
+ * `surfaceId` in its id, so {@link zone} has `renderMarkup` write it, and only
42
+ * already-rendered markup is joined inside. Everything with a dynamic value in
43
+ * it goes through `renderMarkup`.
43
44
  *
44
45
  * ## Dark only
45
46
  *
@@ -51,6 +52,7 @@
51
52
  import { type Theme, type ViewerDocument } from '@issuegraph/viewer';
52
53
  import type { EdgeId, InvalidCode, MutationId, OrderChange, OrderStatus, ProjectedEdge } from '@issuegraph/store';
53
54
  import type { AuditInput } from '../audit/findings.ts';
55
+ import { type EdgeField } from '@issuegraph/core';
54
56
  import { type AuditWords } from '../audit/panel.ts';
55
57
  import { type EncodingRefusedBlockOptions } from '../audit/refused.ts';
56
58
  import { type CreateDraft } from '../create/draft.ts';
@@ -59,10 +61,11 @@ import type { ChangeWords } from '../reevaluate/words.ts';
59
61
  import { type AuditOverlay } from '../audit/surface.ts';
60
62
  import { type ScaleState } from '../scale/commands.ts';
61
63
  import { type InspectorView } from './inspector.ts';
64
+ import { type CanvasMode, type NarrowView } from './narrow.ts';
62
65
  import { type RailWindow, type RailWindowOptions } from './rail.ts';
63
66
  import { type ConflictDiff } from './recovery.ts';
64
67
  import { type WorkspaceSelection } from './selection.ts';
65
- /** The four fixed positions. A closed union, which is what keeps `zone` safe. */
68
+ /** The four fixed positions. */
66
69
  export declare const ZONES: readonly ["header", "rail", "canvas", "inspector"];
67
70
  export type Zone = (typeof ZONES)[number];
68
71
  export interface WorkspaceWords {
@@ -139,6 +142,13 @@ export interface WorkspaceWords {
139
142
  readonly inspector: string;
140
143
  /** Shown in the inspector when nothing is selected. */
141
144
  readonly nothingSelected: string;
145
+ /**
146
+ * The inspector's heading with two or more issues selected: *"3 issues
147
+ * selected"*. A function for the reason `filteredDenominator` is one: the
148
+ * count sits inside the sentence and its grammar moves with it, so the host
149
+ * writes the sentence.
150
+ */
151
+ readonly issuesSelected: (count: number) => string;
142
152
  /**
143
153
  * The control that returns to nothing selected.
144
154
  *
@@ -406,6 +416,16 @@ export interface WorkspaceWords {
406
416
  * are safely the same.
407
417
  */
408
418
  readonly rail?: RailWords | undefined;
419
+ /**
420
+ * The layout under `640`: its three tabs, and the Related groups list's
421
+ * sentence for nothing selected.
422
+ *
423
+ * REQUIRED, unlike `canvas` and `rail`. The tabs are the only way between the
424
+ * three views at that width, and every render draws them, so there is no
425
+ * absent state that would still work: a tab with no name is a control a
426
+ * screen reader announces as nothing.
427
+ */
428
+ readonly narrow: NarrowWords;
409
429
  }
410
430
  /**
411
431
  * Frame 17a's canvas toolbar reads `focus: #512 · 1 hop · 6 of 312 shown`, and
@@ -498,6 +518,35 @@ export interface RailWords {
498
518
  */
499
519
  readonly hide: string;
500
520
  }
521
+ /**
522
+ * The words of the layout under `640`, where one of Order, Related groups and
523
+ * Sub-issues shows at a time.
524
+ */
525
+ export interface NarrowWords {
526
+ /** The tab that shows the order. */
527
+ readonly order: string;
528
+ /** The tab that lists the selection's relationships. */
529
+ readonly related: string;
530
+ /** The tab that shows the sub-issue tree. */
531
+ readonly subIssues: string;
532
+ /**
533
+ * Names the control that closes the Inspector's sheet under `640`. Nothing
534
+ * in this version draws that sheet, so nothing reads this yet.
535
+ */
536
+ readonly closeSheet: string;
537
+ /** What the Related groups list says while nothing is selected. */
538
+ readonly noSelection: string;
539
+ /** Labels the Related groups search field. */
540
+ readonly searchRelated: string;
541
+ /**
542
+ * Says how many matches the Related groups list left out past its 60-row
543
+ * cut: *"12 more — narrow the search"*. A function for the reason
544
+ * `filteredDenominator` is one: the count sits inside the sentence.
545
+ */
546
+ readonly omitted: (count: number) => string;
547
+ /** What the Related groups list says when a search matched nothing. */
548
+ readonly noMatch: string;
549
+ }
501
550
  export interface RecoveryWords {
502
551
  /** Names the state on a failed card. */
503
552
  readonly failed: string;
@@ -889,22 +938,45 @@ export interface WorkspaceOptions {
889
938
  */
890
939
  readonly diffOpen?: MutationId | null | undefined;
891
940
  /**
892
- * A value unique to this surface, used to bind §17a's rail footer to the
893
- * isolated list the canvas draws.
894
- *
895
- * SUPPLIED BY WHOEVER KNOWS THE PAGE. The footer's toggle and the list are in
896
- * different zones, so the toggle names the list with `aria-controls` — and an
897
- * id invented in here would be emitted twice by a host rendering two
898
- * workspaces, leaving the second toggle pointing at the first surface's list.
899
- * `scale/render.ts`'s `searchSpec` records the same hazard for its own label.
900
- *
901
- * ABSENT, NO ASSOCIATION IS DRAWN, and that is the honest default rather than
902
- * a degraded one: `mountWorkspace` mints a value per mount, and markup served
903
- * WITHOUT a mount is not operable anyway — the same argument
904
- * `CanvasWords.editMode` is optional under. A toggle nobody can press needs no
905
- * `aria-controls`.
941
+ * A value unique to this surface, used to bind controls in one zone to what
942
+ * they open in another: §17a's rail footer to the isolated list the canvas
943
+ * draws, and each narrow tab to the zone it shows.
944
+ *
945
+ * SUPPLIED BY WHOEVER KNOWS THE PAGE. A control names its target with
946
+ * `aria-controls`, and an id invented in here would be emitted twice by a
947
+ * host rendering two workspaces, leaving the second surface's controls
948
+ * pointing at the first surface's elements. `scale/render.ts`'s `searchSpec`
949
+ * records the same hazard for its own label. `mountWorkspace` mints a value
950
+ * per mount, so a PAGE THAT DRAWS MORE THAN ONE WORKSPACE WITHOUT A MOUNT
951
+ * PASSES ONE PER WORKSPACE.
952
+ *
953
+ * ABSENT, THE RAIL FOOTER DRAWS NO ASSOCIATION, and that is the honest
954
+ * default rather than a degraded one: markup served without a mount is not
955
+ * operable anyway — the same argument `CanvasWords.editMode` is optional
956
+ * under. A toggle nobody can press needs no `aria-controls`.
957
+ *
958
+ * THE ZONE FRAMES ARE THE ONE EXCEPTION, and they take the fixed ids
959
+ * `ig-zone-<zone>` when this is absent. The tabs are drawn on every render
960
+ * and a tab must name the panel it shows, so a tab with no `aria-controls`
961
+ * would be a broken tab rather than an absent one. The cost is the hazard
962
+ * above, for a page that draws two unmounted workspaces with no value here.
906
963
  */
907
964
  readonly surfaceId?: string | undefined;
965
+ /**
966
+ * Which zone the layout under `640` shows. See `HostState.narrowView`.
967
+ * Absent is `'order'`.
968
+ */
969
+ readonly narrowView?: NarrowView | undefined;
970
+ /**
971
+ * What the canvas zone draws. The tree itself is drawn by `mountWorkspace`;
972
+ * this only tells the tabs which one is selected. Absent is
973
+ * `'neighbourhood'`.
974
+ */
975
+ readonly canvas?: CanvasMode | undefined;
976
+ /** The Related groups list's open group. See `HostState.relatedGroup`. */
977
+ readonly relatedGroup?: EdgeField | null | undefined;
978
+ /** The Related groups list's search text. See `HostState.relatedQuery`. */
979
+ readonly relatedQuery?: string | undefined;
908
980
  }
909
981
  export interface WorkspaceView {
910
982
  readonly selection: WorkspaceSelection;
@@ -929,6 +1001,17 @@ export interface WorkspaceResult {
929
1001
  readonly styles: string;
930
1002
  readonly diagnostics: readonly string[];
931
1003
  }
1004
+ /**
1005
+ * The search's status line, right under the field: that a search matched
1006
+ * nothing, or how many matches the 60-row cut left out, and empty otherwise.
1007
+ *
1008
+ * DRAWN WHENEVER THE SEARCH IS, EMPTY OR NOT. A live region that is created
1009
+ * already holding its text is not reliably announced; it has to exist first
1010
+ * and then change. So it is always in the markup beside the field, and
1011
+ * `mountWorkspace` carries the element across redraws (`RELATED_STATUS`), as
1012
+ * it carries §17c's change line, so typing changes its text and nothing else.
1013
+ */
1014
+ export declare const RELATED_STATUS_CLASS = "ig-related-status";
932
1015
  /** Render one document at one reader position, as the whole workspace. */
933
1016
  export declare function renderWorkspace(input: ViewerDocument, options: WorkspaceOptions): WorkspaceResult;
934
1017
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/workspace/render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/workspace/render.ts"],"names":[],"mappings":"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"}
@@ -32,14 +32,15 @@
32
32
  * clean — which is the audit failing silently on exactly the rows where an
33
33
  * encoding error is hardest to see.
34
34
  *
35
- * ## The zone frames, and the one place a tag is written here
35
+ * ## The zone frames, and the one place markup is joined here
36
36
  *
37
37
  * Two of the four zones hand back a STRING rather than a spec — the ladder's
38
38
  * chrome and the audit header — so the frames are assembled by concatenation,
39
39
  * as `renderScaleLadder` already assembles its own canvas and chrome. What
40
- * makes that safe is not care: {@link ZONES} is a closed union of literals, so
41
- * no caller value can reach an attribute here at all, and `zones.test.ts` pins
42
- * it. Everything with a dynamic value in it goes through `renderMarkup`.
40
+ * makes that safe is not care: a frame's own opening tag carries the caller's
41
+ * `surfaceId` in its id, so {@link zone} has `renderMarkup` write it, and only
42
+ * already-rendered markup is joined inside. Everything with a dynamic value in
43
+ * it goes through `renderMarkup`.
43
44
  *
44
45
  * ## Dark only
45
46
  *
@@ -48,7 +49,7 @@
48
49
  * forked token set here and no second palette: the theme is the viewer's, and
49
50
  * `styles.ts` writes structure against its custom properties.
50
51
  */
51
- import { KEY_ATTRIBUTE, element, glyphAndLabel, hiddenGlyph, identity, labelFrom, normalizeDocument, renderMarkup, provenanceClause, renderViewer, resolveTheme, themeCss, treatmentFor, viewerStylesheet, } from '@issuegraph/viewer';
52
+ import { KEY_ATTRIBUTE, element, glyphAndLabel, hiddenGlyph, identity, labelFrom, normalizeDocument, renderMarkup, provenanceClause, recedingOf, renderViewer, resolveTheme, themeCss, treatmentFor, viewerStylesheet, } from '@issuegraph/viewer';
52
53
  import { edgeIdentity } from '@issuegraph/core';
53
54
  import { renderAuditPanel } from "../audit/panel.js";
54
55
  import { renderEncodingRefusedBlock } from "../audit/refused.js";
@@ -65,21 +66,61 @@ import { INITIAL_SCALE_STATE } from "../scale/commands.js";
65
66
  import { renderScaleLadder } from "../scale/render.js";
66
67
  import { scaleLadderStylesheet } from "../scale/styles.js";
67
68
  import { inspectorView, } from "./inspector.js";
69
+ import { NARROW_TABS, narrowTabOf } from "./narrow.js";
68
70
  import { railWindow } from "./rail.js";
71
+ import { relatedListView } from "./related.js";
69
72
  import { diffIsEmpty, diffWithin } from "./recovery.js";
70
- import { INITIAL_SELECTION, selectedEdgeId, selectedKey, } from "./selection.js";
73
+ import { INITIAL_SELECTION, selectedEdgeId, selectedKeys, } from "./selection.js";
71
74
  import { workspaceStylesheet } from "./styles.js";
72
- /** The four fixed positions. A closed union, which is what keeps `zone` safe. */
75
+ /** The four fixed positions. */
73
76
  export const ZONES = Object.freeze(['header', 'rail', 'canvas', 'inspector']);
77
+ const ZONE_CLOSE = '</section>';
74
78
  /**
75
- * A zone frame.
79
+ * A zone frame, around already-rendered markup from `renderMarkup` or from a
80
+ * sibling leaf's renderer.
76
81
  *
77
- * The only tag written by hand in this package, and it takes no caller value:
78
- * `zone` is one of {@link ZONES} and `inner` is already-rendered markup from
79
- * `renderMarkup` or from a sibling leaf's renderer.
82
+ * THE OPENING TAG IS `renderMarkup`'S, because the id carries the caller's
83
+ * `surfaceId` and only that function escapes an attribute in this package. It
84
+ * renders the frame empty and the inner markup goes where its closing tag was.
80
85
  */
81
- function zone(name, inner) {
82
- return `<section class="ig-zone" data-zone="${name}">${inner}</section>`;
86
+ function zone(name, id, inner) {
87
+ const frame = renderMarkup(element('section', { class: 'ig-zone', 'data-zone': name, id }, []));
88
+ return `${frame.slice(0, -ZONE_CLOSE.length)}${inner}${ZONE_CLOSE}`;
89
+ }
90
+ /** Each zone frame's id, unique on the page when the caller supplied a `surfaceId`. */
91
+ function zoneIds(surfaceId) {
92
+ const suffix = surfaceId === undefined ? '' : `-${surfaceId}`;
93
+ return {
94
+ header: `ig-zone-header${suffix}`,
95
+ rail: `ig-zone-rail${suffix}`,
96
+ canvas: `ig-zone-canvas${suffix}`,
97
+ inspector: `ig-zone-inspector${suffix}`,
98
+ };
99
+ }
100
+ /** The zone each narrow tab shows, and the word that names it. */
101
+ const NARROW_TAB_PARTS = Object.freeze({
102
+ order: { zone: 'rail', word: 'order' },
103
+ related: { zone: 'canvas', word: 'related' },
104
+ 'sub-issues': { zone: 'canvas', word: 'subIssues' },
105
+ });
106
+ /**
107
+ * The tabs of the layout under `640`.
108
+ *
109
+ * ALWAYS DRAWN, AND HIDDEN BY THE SHEET AT THE WIDER LAYOUTS, for the reason the
110
+ * canvas strip is: this function does not know how wide it is. Every tab is a
111
+ * tab stop rather than one roving stop, so each is reachable the way every other
112
+ * control on this surface is.
113
+ */
114
+ function narrowTabsSpec(selected, words, ids) {
115
+ return element('div', { class: 'ig-narrow-tabs', role: 'tablist' }, NARROW_TABS.map((tab) => element('button', {
116
+ type: 'button',
117
+ class: 'ig-narrow-tab',
118
+ role: 'tab',
119
+ 'data-ig-command': 'narrow-tab',
120
+ 'data-ig-value': tab,
121
+ 'aria-selected': tab === selected ? 'true' : 'false',
122
+ 'aria-controls': ids[NARROW_TAB_PARTS[tab].zone],
123
+ }, [words[NARROW_TAB_PARTS[tab].word]])));
83
124
  }
84
125
  /**
85
126
  * §17f's canvas caption — what this canvas is drawing, and out of how much.
@@ -627,6 +668,97 @@ function relationshipSpec(relationship, subject, selected, words, refused) {
627
668
  flipControl(relationship, selected, words),
628
669
  ]);
629
670
  }
671
+ /**
672
+ * The Related groups list's rows: the Inspector's own head in the Inspector's
673
+ * own row box, so a relationship reads the same words, direction and hue here.
674
+ * Only the head: removing, retyping and flipping stay the Inspector's.
675
+ */
676
+ function relatedRowsSpec(rows, subject) {
677
+ return element('ul', { class: 'ig-related-rows' }, rows.map((row) => element('li', { class: 'ig-relationship', 'data-edge': row.field }, [relationshipHead(row, subject)])));
678
+ }
679
+ /**
680
+ * The Related groups search. The input sits inside its label, so the two are
681
+ * associated without an `id`, for the reason `scale/render.ts`'s `searchSpec`
682
+ * gives. Named by the host's own search label.
683
+ */
684
+ function relatedSearchSpec(query, words) {
685
+ return element('label', { class: 'ig-related-search' }, [
686
+ words.searchRelated,
687
+ element('input', {
688
+ type: 'search',
689
+ 'data-ig-command': 'related-query',
690
+ value: query,
691
+ autocomplete: 'off',
692
+ }),
693
+ ]);
694
+ }
695
+ /** One kind's group control, worded as the Inspector words that kind, then its count. */
696
+ function relatedGroupSpec(field, count, open) {
697
+ const treatment = treatmentFor(field);
698
+ return element('button', {
699
+ type: 'button',
700
+ class: 'ig-related-group',
701
+ 'data-ig-command': 'related-group',
702
+ 'data-ig-value': field,
703
+ 'aria-expanded': open ? 'true' : 'false',
704
+ }, [...glyphAndLabel(treatment.glyph, labelFrom(treatment, true)), ' ', element('span', {}, [String(count)])]);
705
+ }
706
+ /**
707
+ * The search's status line, right under the field: that a search matched
708
+ * nothing, or how many matches the 60-row cut left out, and empty otherwise.
709
+ *
710
+ * DRAWN WHENEVER THE SEARCH IS, EMPTY OR NOT. A live region that is created
711
+ * already holding its text is not reliably announced; it has to exist first
712
+ * and then change. So it is always in the markup beside the field, and
713
+ * `mountWorkspace` carries the element across redraws (`RELATED_STATUS`), as
714
+ * it carries §17c's change line, so typing changes its text and nothing else.
715
+ */
716
+ export const RELATED_STATUS_CLASS = 'ig-related-status';
717
+ function relatedStatusSpec(view, words) {
718
+ const said = view.noMatch ? words.noMatch : view.omitted > 0 ? words.omitted(view.omitted) : null;
719
+ return element('p', { class: RELATED_STATUS_CLASS, role: 'status' }, said === null ? [] : [said]);
720
+ }
721
+ /**
722
+ * The Related groups list, drawn in the canvas zone under `640`.
723
+ *
724
+ * EVERY DECISION IS `relatedListView`'S — which rows, which groups, whether a
725
+ * search is drawn and how many rows were cut. This only gives each part its
726
+ * element, so the 60-row cap is enforced in one place.
727
+ *
728
+ * An open group draws its search and its rows inside its own item, under its
729
+ * control. A search over every relationship sits above the groups, and while it
730
+ * holds a query its matches stand where the groups were.
731
+ */
732
+ function relatedListSpec(view, subject, query, words) {
733
+ return element('div', {
734
+ class: 'ig-related',
735
+ 'data-ig-omitted': view.kind === 'grouped' && view.omitted > 0 ? view.omitted : undefined,
736
+ }, relatedListParts(view, subject, query, words));
737
+ }
738
+ function relatedListParts(view, subject, query, words) {
739
+ switch (view.kind) {
740
+ case 'no-selection':
741
+ return [element('p', { class: 'ig-related-empty' }, [words.narrow.noSelection])];
742
+ case 'no-relationships':
743
+ return [element('p', { class: 'ig-related-empty' }, [words.noRelationships])];
744
+ case 'flat':
745
+ return [relatedRowsSpec(view.rows, subject)];
746
+ case 'grouped': {
747
+ const search = view.search === 'none' ? null : relatedSearchSpec(query, words.narrow);
748
+ const status = view.search === 'none' ? null : relatedStatusSpec(view, words.narrow);
749
+ const open = view.groups.some((group) => group.open);
750
+ const groups = element('ul', { class: 'ig-related-groups' }, view.groups.map((group) => element('li', {}, [
751
+ relatedGroupSpec(group.field, group.count, group.open),
752
+ group.open ? search : null,
753
+ group.open ? status : null,
754
+ group.open ? relatedRowsSpec(view.rows, subject) : null,
755
+ ])));
756
+ if (open)
757
+ return [groups];
758
+ return [search, status, view.groups.length > 0 ? groups : relatedRowsSpec(view.rows, subject)];
759
+ }
760
+ }
761
+ }
630
762
  /**
631
763
  * A refused relationship, drawn where the reader was building it.
632
764
  *
@@ -998,6 +1130,14 @@ function headerMarkup(host, auditHeader, words) {
998
1130
  ];
999
1131
  return `<div class="ig-workspace-header">${parts.join('')}</div>`;
1000
1132
  }
1133
+ /**
1134
+ * The selection as the viewer's `selected` takes it: one key as a string, a
1135
+ * set as its keys in addition order, and nothing for an edge or none.
1136
+ */
1137
+ function viewerSelected(selection) {
1138
+ const keys = selectedKeys(selection);
1139
+ return keys.length > 1 ? keys : (keys[0] ?? null);
1140
+ }
1001
1141
  function panelScope(view) {
1002
1142
  const { subject } = view;
1003
1143
  switch (subject.kind) {
@@ -1008,6 +1148,10 @@ function panelScope(view) {
1008
1148
  kind: 'issue',
1009
1149
  keys: new Set([subject.issue.key, ...(subject.whyRank?.unitPartners ?? [])]),
1010
1150
  };
1151
+ // A SET STATES NOTHING. It offers no edit, so no refusal or recovery is
1152
+ // about an edit made from it; each one stays on its own issue's panel.
1153
+ case 'issues':
1154
+ return { kind: 'none' };
1011
1155
  case 'edge':
1012
1156
  return { kind: 'edge', edgeId: subject.relationship.edgeId };
1013
1157
  }
@@ -1347,6 +1491,20 @@ function inspectorSpec(view, context) {
1347
1491
  : whyRankSpec(subject.whyRank, words, subject.whyRank.holds.map((hold) => holdRow(hold, context.known, (subjectKey) => context.leadOf.get(subjectKey) === context.leadOf.get(subject.issue.key)))),
1348
1492
  ])
1349
1493
  : null,
1494
+ // A SET SAYS HOW MANY AND LISTS THEM, in the order they were added, as
1495
+ // text: no link, no command and no key attribute, so the list is
1496
+ // agreement with the rail and the canvas, not a second place to act. The
1497
+ // batch offers are a later change.
1498
+ subject.kind === 'issues'
1499
+ ? element('div', { class: 'ig-inspector-issues' }, [
1500
+ element('h3', { class: 'ig-inspector-title' }, [words.issuesSelected(subject.issues.length)]),
1501
+ element('ul', { class: 'ig-inspector-set' }, subject.issues.map((issue) => element('li', { class: 'ig-inspector-set-item' }, [
1502
+ element('span', { class: 'ig-title' }, [issue.title]),
1503
+ ' ',
1504
+ element('span', { class: 'ig-id' }, [issue.key]),
1505
+ ]))),
1506
+ ])
1507
+ : null,
1350
1508
  // ONE DERIVATION, READ TWICE. The step is asked once here and both
1351
1509
  // placements below read the answer, so the header and the body cannot
1352
1510
  // disagree about WHICH step is live. What each draws for a given arm is
@@ -1355,7 +1513,10 @@ function inspectorSpec(view, context) {
1355
1513
  // unrepresentable, and a value read at two sites does not. The pin that
1356
1514
  // stands where the return ordering used to is the one asserting no `add`
1357
1515
  // control exists anywhere in the panel at the kind step.
1358
- element('div', { class: 'ig-inspector-relationships', 'data-filtered': view.filtered ? 'true' : 'false' }, [
1516
+ // NO RELATIONSHIP REGION FOR A SET: it lists none and offers no `+ add`,
1517
+ // and "no relationships" under a list of issues would read as a fact
1518
+ // about them.
1519
+ subject.kind === 'issues' ? null : element('div', { class: 'ig-inspector-relationships', 'data-filtered': view.filtered ? 'true' : 'false' }, [
1359
1520
  // §17a PUTS `+ add` ON THE HEADING'S OWN ROW, and the reason is the
1360
1521
  // list between them: it is unbounded, so a control after it drifts
1361
1522
  // down the panel as a subject gains relationships and is below the
@@ -1685,9 +1846,14 @@ export function renderWorkspace(input, options) {
1685
1846
  // back on `scene.footer`, it is composed after the trailing spacer below.
1686
1847
  // See `SceneOptions.detachFooter`.
1687
1848
  detachFooter: true,
1688
- // The rail is where a selected ISSUE reads as current. An edge selection
1689
- // resolves to no key, which is `selectedKey`'s whole job.
1690
- selected: selectedKey(selection),
1849
+ // The rail is where a selected ISSUE reads as current, and every member of
1850
+ // a set does. An edge selection resolves to no key.
1851
+ selected: viewerSelected(selection),
1852
+ // WORKED OUT OVER THE WHOLE DOCUMENT, NOT THE WINDOW. `rail.document` holds
1853
+ // only the window's issues and edges, so a selection outside it would
1854
+ // recede nothing here while the canvas recedes around it. An edge
1855
+ // selection recedes the rail too, and so does a set, member by member.
1856
+ receding: recedingOf(document, { key: viewerSelected(selection), edge: selectedEdgeId(selection) }),
1691
1857
  // §16f. Passed WHOLE rather than windowed: the window moves, and a reader
1692
1858
  // who opened a row, scrolled past it and came back should find it open.
1693
1859
  // A key the window does not draw costs one `includes` miss and nothing else.
@@ -1752,7 +1918,7 @@ export function renderWorkspace(input, options) {
1752
1918
  // selected issue as ordinary while the rail marked it current, so the
1753
1919
  // single selection this surface advertises disagreed with itself between
1754
1920
  // two zones on every render.
1755
- selected: selectedKey(selection),
1921
+ selected: viewerSelected(selection),
1756
1922
  // AND ITS OTHER HALF. The union has two payloads, and reading only the
1757
1923
  // issue one left the canvas the single zone that could not see an edge
1758
1924
  // selection: the inspector filtered to the edge while the canvas drew it
@@ -1810,9 +1976,14 @@ export function renderWorkspace(input, options) {
1810
1976
  // Suppressing the markup with an option would put the key out of reach of
1811
1977
  // both.
1812
1978
  const canvasLegend = canvas.ladder.tier === 'direct' ? 'drawn' : 'absent';
1979
+ // THE TAB IS READ OFF THE VIEW AND THE MODE, never handed in, so the selected
1980
+ // tab cannot disagree with what the canvas zone draws. See `narrowTabOf`.
1981
+ const tab = narrowTabOf(options.narrowView ?? 'order', options.canvas ?? 'neighbourhood');
1813
1982
  const narrowState = ` data-canvas="${canvasOpen ? 'open' : 'strip'}"` +
1814
1983
  ` data-canvas-legend="${canvasLegend}"` +
1815
- ` data-inspector="${lifted ? 'lifted' : 'dismissed'}"`;
1984
+ ` data-inspector="${lifted ? 'lifted' : 'dismissed'}"` +
1985
+ ` data-tab="${tab}"`;
1986
+ const ids = zoneIds(options.surfaceId);
1816
1987
  // §17a'S RAIL FOOTER, FROM THE LADDER THE CANVAS ALREADY DERIVED. `isolated`
1817
1988
  // is a property of the whole document rather than of the tier the canvas
1818
1989
  // settled on, so the rail and the canvas cannot disagree about it: there is
@@ -1825,6 +1996,14 @@ export function renderWorkspace(input, options) {
1825
1996
  // scope is a reading hazard worth one name, not one comment per use.
1826
1997
  const railFooterSpec = railFooter(canvas.ladder.isolated, options.words.rail, isolatedListId);
1827
1998
  const inspector = inspectorView(document, selection);
1999
+ // The Related groups list, drawn only while its tab is the one selected: the
2000
+ // other two tabs show nothing of it, and the wider layouts hide it.
2001
+ const relatedList = tab !== 'related'
2002
+ ? ''
2003
+ : renderMarkup(relatedListSpec(relatedListView(document, selection, {
2004
+ group: options.relatedGroup ?? null,
2005
+ query: options.relatedQuery ?? '',
2006
+ }), inspector.subject.kind === 'issue' ? inspector.subject.issue.key : null, options.relatedQuery ?? '', options.words));
1828
2007
  // §17c'S LOOP, OVER THE RAIL THE READER IS ACTUALLY LOOKING AT.
1829
2008
  // `reevaluateView` is handed the WINDOWED scene, so a chip whose row is
1830
2009
  // scrolled out of the window resolves to no row and draws nowhere — which is
@@ -1931,7 +2110,7 @@ export function renderWorkspace(input, options) {
1931
2110
  //
1932
2111
  // §17k'S TWO READER DECISIONS RIDE THE SAME ROOT, and for the same reason
1933
2112
  // `data-order` does: the stylesheet is the only party that knows which of
1934
- // the three layouts is drawn, so the surface publishes what the reader
2113
+ // the four layouts is drawn, so the surface publishes what the reader
1935
2114
  // asked for and each container block reads the one it has a use for.
1936
2115
  // Neither attribute means anything at the width where its zone is a zone.
1937
2116
  //
@@ -1943,7 +2122,7 @@ export function renderWorkspace(input, options) {
1943
2122
  changeWords === undefined
1944
2123
  ? `<div class="ig-workspace"${narrowState}>`
1945
2124
  : `<div class="ig-workspace" data-order="${orderStatus}"${narrowState}>`,
1946
- zone('header', [
2125
+ zone('header', ids.header, [
1947
2126
  headerMarkup(document.host, overlay === null ? '' : renderAuditHeader(overlay, { open: auditOpen }), options.words),
1948
2127
  // §17c'S SUMMARY LIVES IN THE HEADER, NOT AT THE TOP OF THE RAIL, and
1949
2128
  // the frame draws them adjacent so this is a real departure worth the
@@ -1969,8 +2148,12 @@ export function renderWorkspace(input, options) {
1969
2148
  changeWords === undefined
1970
2149
  ? ''
1971
2150
  : renderMarkup(summarySpec(change.summary, changeWords, { held: change.held })),
2151
+ // THE TABS ARE THE HEADER'S LAST CHILD, because the header is the one
2152
+ // zone nothing replaces after this render: the mount swaps the canvas
2153
+ // zone's children for the tree, and a tab inside it would vanish there.
2154
+ renderMarkup(narrowTabsSpec(tab, options.words.narrow, ids)),
1972
2155
  ].join('')),
1973
- zone('rail', [
2156
+ zone('rail', ids.rail, [
1974
2157
  railSpacer(rail.before, 'before'),
1975
2158
  renderMarkup(markRailRows(railRender.scene.root)),
1976
2159
  railSpacer(rail.after, 'after'),
@@ -1982,14 +2165,13 @@ export function renderWorkspace(input, options) {
1982
2165
  railRender.scene.footer === null ? '' : renderMarkup(markRailRows(railRender.scene.footer)),
1983
2166
  railFooterSpec === null ? '' : renderMarkup(railFooterSpec),
1984
2167
  ].join('')),
1985
- zone('canvas',
2168
+ zone('canvas', ids.canvas,
1986
2169
  // THE CAPTION LEADS THE ZONE, above the graph, exactly as frame 17a
1987
2170
  // draws it — and it is assembled HERE rather than inside the ladder.
1988
2171
  // `renderScaleLadder` is also used standalone, where `chrome: false` is
1989
2172
  // the deliberate answer, and the words this row needs are the
1990
2173
  // workspace's. Both halves are already-rendered markup, which is the
1991
- // rule `zone` exists under: it writes the only hand-authored tag in this
1992
- // package and takes no caller value.
2174
+ // rule `zone` exists under: it frames markup that was already escaped.
1993
2175
  //
1994
2176
  // THE STRIP CONTROL LEADS THE ZONE, above the caption, because below
1995
2177
  // `1120` it is the ONLY thing in the zone the reader can reach: the
@@ -2006,9 +2188,10 @@ export function renderWorkspace(input, options) {
2006
2188
  [strip, toolbar]
2007
2189
  .map((spec) => (spec === null ? '' : renderMarkup(spec)))
2008
2190
  .join('') +
2191
+ relatedList +
2009
2192
  canvas.markup +
2010
2193
  auditPanel),
2011
- zone('inspector',
2194
+ zone('inspector', ids.inspector,
2012
2195
  // §17d'S AUDIT IS THE SELECTION'S SIBLING, AND THEY SHARE ONE SCROLL
2013
2196
  // TRACK. Sibling rather than child so each surface keeps its own padding
2014
2197
  // and reads as a peer of the selection rather than part of it — their
@@ -2040,9 +2223,8 @@ export function renderWorkspace(input, options) {
2040
2223
  // track is what avoids needing panes at all.
2041
2224
  //
2042
2225
  // BOTH SIDES ARE ALREADY-RENDERED MARKUP, which is the rule `zone` exists
2043
- // under: it writes the only hand-authored tag in this package and takes
2044
- // no caller value, and everything with a dynamic value in it went through
2045
- // `renderMarkup`.
2226
+ // under: everything with a dynamic value in it went through
2227
+ // `renderMarkup`, the frame's own id included.
2046
2228
  //
2047
2229
  // `known` IS THE DRAWN DOCUMENT'S KEYS, the same set `holdRow` withholds
2048
2230
  // its subject control on, and NOT the audit's: a host audits what it