@issuegraph/editor 0.1.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/LICENSE +201 -0
- package/README.md +238 -0
- package/dist/audit/findings.d.ts +225 -0
- package/dist/audit/findings.d.ts.map +1 -0
- package/dist/audit/findings.js +348 -0
- package/dist/audit/findings.js.map +1 -0
- package/dist/audit/styles.d.ts +37 -0
- package/dist/audit/styles.d.ts.map +1 -0
- package/dist/audit/styles.js +72 -0
- package/dist/audit/styles.js.map +1 -0
- package/dist/audit/surface.d.ts +155 -0
- package/dist/audit/surface.d.ts.map +1 -0
- package/dist/audit/surface.js +202 -0
- package/dist/audit/surface.js.map +1 -0
- package/dist/create/draft.d.ts +119 -0
- package/dist/create/draft.d.ts.map +1 -0
- package/dist/create/draft.js +114 -0
- package/dist/create/draft.js.map +1 -0
- package/dist/create/keys.d.ts +225 -0
- package/dist/create/keys.d.ts.map +1 -0
- package/dist/create/keys.js +228 -0
- package/dist/create/keys.js.map +1 -0
- package/dist/create/placement.d.ts +69 -0
- package/dist/create/placement.d.ts.map +1 -0
- package/dist/create/placement.js +76 -0
- package/dist/create/placement.js.map +1 -0
- package/dist/firstpass/batch.d.ts +190 -0
- package/dist/firstpass/batch.d.ts.map +1 -0
- package/dist/firstpass/batch.js +143 -0
- package/dist/firstpass/batch.js.map +1 -0
- package/dist/firstpass/candidates.d.ts +128 -0
- package/dist/firstpass/candidates.d.ts.map +1 -0
- package/dist/firstpass/candidates.js +39 -0
- package/dist/firstpass/candidates.js.map +1 -0
- package/dist/firstpass/keys.d.ts +90 -0
- package/dist/firstpass/keys.d.ts.map +1 -0
- package/dist/firstpass/keys.js +112 -0
- package/dist/firstpass/keys.js.map +1 -0
- package/dist/firstpass/queue.d.ts +183 -0
- package/dist/firstpass/queue.d.ts.map +1 -0
- package/dist/firstpass/queue.js +159 -0
- package/dist/firstpass/queue.js.map +1 -0
- package/dist/firstpass/render.d.ts +100 -0
- package/dist/firstpass/render.d.ts.map +1 -0
- package/dist/firstpass/render.js +216 -0
- package/dist/firstpass/render.js.map +1 -0
- package/dist/firstpass/styles.d.ts +36 -0
- package/dist/firstpass/styles.d.ts.map +1 -0
- package/dist/firstpass/styles.js +148 -0
- package/dist/firstpass/styles.js.map +1 -0
- package/dist/firstpass/view.d.ts +82 -0
- package/dist/firstpass/view.d.ts.map +1 -0
- package/dist/firstpass/view.js +60 -0
- package/dist/firstpass/view.js.map +1 -0
- package/dist/firstpass/words.d.ts +105 -0
- package/dist/firstpass/words.d.ts.map +1 -0
- package/dist/firstpass/words.js +28 -0
- package/dist/firstpass/words.js.map +1 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/overlay/grammar.d.ts +259 -0
- package/dist/overlay/grammar.d.ts.map +1 -0
- package/dist/overlay/grammar.js +223 -0
- package/dist/overlay/grammar.js.map +1 -0
- package/dist/overlay/render.d.ts +125 -0
- package/dist/overlay/render.d.ts.map +1 -0
- package/dist/overlay/render.js +439 -0
- package/dist/overlay/render.js.map +1 -0
- package/dist/overlay/styles.d.ts +41 -0
- package/dist/overlay/styles.d.ts.map +1 -0
- package/dist/overlay/styles.js +124 -0
- package/dist/overlay/styles.js.map +1 -0
- package/dist/picker/render.d.ts +80 -0
- package/dist/picker/render.d.ts.map +1 -0
- package/dist/picker/render.js +112 -0
- package/dist/picker/render.js.map +1 -0
- package/dist/picker/styles.d.ts +26 -0
- package/dist/picker/styles.d.ts.map +1 -0
- package/dist/picker/styles.js +116 -0
- package/dist/picker/styles.js.map +1 -0
- package/dist/picker/view.d.ts +135 -0
- package/dist/picker/view.d.ts.map +1 -0
- package/dist/picker/view.js +117 -0
- package/dist/picker/view.js.map +1 -0
- package/dist/picker/words.d.ts +53 -0
- package/dist/picker/words.d.ts.map +1 -0
- package/dist/picker/words.js +28 -0
- package/dist/picker/words.js.map +1 -0
- package/dist/reevaluate/render.d.ts +77 -0
- package/dist/reevaluate/render.d.ts.map +1 -0
- package/dist/reevaluate/render.js +211 -0
- package/dist/reevaluate/render.js.map +1 -0
- package/dist/reevaluate/styles.d.ts +24 -0
- package/dist/reevaluate/styles.d.ts.map +1 -0
- package/dist/reevaluate/styles.js +182 -0
- package/dist/reevaluate/styles.js.map +1 -0
- package/dist/reevaluate/view.d.ts +102 -0
- package/dist/reevaluate/view.d.ts.map +1 -0
- package/dist/reevaluate/view.js +111 -0
- package/dist/reevaluate/view.js.map +1 -0
- package/dist/reevaluate/words.d.ts +54 -0
- package/dist/reevaluate/words.d.ts.map +1 -0
- package/dist/reevaluate/words.js +29 -0
- package/dist/reevaluate/words.js.map +1 -0
- package/dist/scale/commands.d.ts +60 -0
- package/dist/scale/commands.d.ts.map +1 -0
- package/dist/scale/commands.js +49 -0
- package/dist/scale/commands.js.map +1 -0
- package/dist/scale/ladder.d.ts +141 -0
- package/dist/scale/ladder.d.ts.map +1 -0
- package/dist/scale/ladder.js +243 -0
- package/dist/scale/ladder.js.map +1 -0
- package/dist/scale/render.d.ts +85 -0
- package/dist/scale/render.d.ts.map +1 -0
- package/dist/scale/render.js +194 -0
- package/dist/scale/render.js.map +1 -0
- package/dist/scale/styles.d.ts +21 -0
- package/dist/scale/styles.d.ts.map +1 -0
- package/dist/scale/styles.js +105 -0
- package/dist/scale/styles.js.map +1 -0
- package/dist/workspace/inspector.d.ts +117 -0
- package/dist/workspace/inspector.d.ts.map +1 -0
- package/dist/workspace/inspector.js +140 -0
- package/dist/workspace/inspector.js.map +1 -0
- package/dist/workspace/rail.d.ts +122 -0
- package/dist/workspace/rail.d.ts.map +1 -0
- package/dist/workspace/rail.js +216 -0
- package/dist/workspace/rail.js.map +1 -0
- package/dist/workspace/render.d.ts +139 -0
- package/dist/workspace/render.d.ts.map +1 -0
- package/dist/workspace/render.js +366 -0
- package/dist/workspace/render.js.map +1 -0
- package/dist/workspace/selection.d.ts +92 -0
- package/dist/workspace/selection.d.ts.map +1 -0
- package/dist/workspace/selection.js +83 -0
- package/dist/workspace/selection.js.map +1 -0
- package/dist/workspace/styles.d.ts +39 -0
- package/dist/workspace/styles.d.ts.map +1 -0
- package/dist/workspace/styles.js +313 -0
- package/dist/workspace/styles.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ladder chrome's structural stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* Same contract as the viewer's, and for the same reason: it carries layout,
|
|
5
|
+
* weight and state, never a value. Every colour, length and font here is a
|
|
6
|
+
* `var(--ig-…)` the host's theme resolves, so a second theme keeps working on
|
|
7
|
+
* the surfaces layer 2 adds rather than only on layer 1's. `styles.test.ts`
|
|
8
|
+
* scans these bytes for a literal colour or a fixed length and for a token the
|
|
9
|
+
* theme does not define, so the rule is enforced rather than remembered.
|
|
10
|
+
*
|
|
11
|
+
* IT ADDS SELECTORS RATHER THAN REDEFINING THEM. The refusal, its capsules and
|
|
12
|
+
* their counts already have a look — this file styles only what layer 2
|
|
13
|
+
* introduces: the ladder container, the routes, the search box, the isolated
|
|
14
|
+
* chip and the list it opens.
|
|
15
|
+
*
|
|
16
|
+
* Shipped as a string for the same reason the viewer's is: an entry that
|
|
17
|
+
* imports CSS cannot be loaded by a bare Node runtime, and a string needs no
|
|
18
|
+
* bundler.
|
|
19
|
+
*/
|
|
20
|
+
export const scaleLadderStylesheet = `
|
|
21
|
+
.ig-ladder {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
gap: var(--ig-space);
|
|
25
|
+
font-family: var(--ig-font-ui);
|
|
26
|
+
font-size: var(--ig-font-size);
|
|
27
|
+
line-height: var(--ig-line-height);
|
|
28
|
+
color: var(--ig-text-body);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.ig-ladder-routes {
|
|
32
|
+
list-style: none;
|
|
33
|
+
margin: 0;
|
|
34
|
+
padding: 0;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
gap: var(--ig-space-tight);
|
|
38
|
+
color: var(--ig-text-muted);
|
|
39
|
+
font-size: var(--ig-font-size-small);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.ig-ladder-search {
|
|
43
|
+
display: flex;
|
|
44
|
+
flex-direction: column;
|
|
45
|
+
gap: var(--ig-space-tight);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.ig-ladder-search input {
|
|
49
|
+
background: var(--ig-surface);
|
|
50
|
+
color: var(--ig-text);
|
|
51
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
52
|
+
border-radius: var(--ig-radius);
|
|
53
|
+
padding: var(--ig-space-tight);
|
|
54
|
+
font-family: var(--ig-font-ui);
|
|
55
|
+
font-size: var(--ig-font-size);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ig-ladder-search input:focus-visible {
|
|
59
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
60
|
+
outline-offset: var(--ig-space-tight);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.ig-ladder-match {
|
|
64
|
+
display: flex;
|
|
65
|
+
gap: var(--ig-space-tight);
|
|
66
|
+
align-items: baseline;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.ig-chip {
|
|
70
|
+
align-self: flex-start;
|
|
71
|
+
background: var(--ig-surface-2);
|
|
72
|
+
color: var(--ig-text-body);
|
|
73
|
+
border: var(--ig-stroke) solid var(--ig-line);
|
|
74
|
+
border-radius: var(--ig-radius);
|
|
75
|
+
padding: var(--ig-space-tight) var(--ig-space);
|
|
76
|
+
font-family: var(--ig-font-ui);
|
|
77
|
+
font-size: var(--ig-font-size-small);
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.ig-chip:focus-visible {
|
|
82
|
+
outline: var(--ig-focus-ring) solid var(--ig-focus);
|
|
83
|
+
outline-offset: var(--ig-space-tight);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ig-chip[aria-expanded='true'] {
|
|
87
|
+
border-color: var(--ig-accent);
|
|
88
|
+
color: var(--ig-text);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.ig-isolated-list {
|
|
92
|
+
list-style: none;
|
|
93
|
+
margin: 0;
|
|
94
|
+
padding: 0;
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
gap: var(--ig-space-tight);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.ig-isolated-list .ig-id {
|
|
101
|
+
font-family: var(--ig-font-mono);
|
|
102
|
+
color: var(--ig-text-muted);
|
|
103
|
+
}
|
|
104
|
+
`;
|
|
105
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/scale/styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoFpC,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inspector: detail, the "why", relationships, and the edit affordances
|
|
3
|
+
* that hang off them.
|
|
4
|
+
*
|
|
5
|
+
* ## It is a projection of the selection, and holds no state of its own
|
|
6
|
+
*
|
|
7
|
+
* §17b makes `selected` the one edge state that also filters the inspector, so
|
|
8
|
+
* this zone is a pure function of the document and that single value. It keeps
|
|
9
|
+
* no "currently inspecting" of its own — a second copy would be free to
|
|
10
|
+
* disagree with the rail and the canvas about what is selected, which is the
|
|
11
|
+
* whole reason the workspace owns exactly one selection.
|
|
12
|
+
*
|
|
13
|
+
* ## An edge selection FILTERS; it does not open a different panel
|
|
14
|
+
*
|
|
15
|
+
* The distinction matters and it is easy to lose. With an edge selected the
|
|
16
|
+
* inspector shows the same relationship list, narrowed to that one edge —
|
|
17
|
+
* rather than a separate edge inspector. So the reader's frame of reference
|
|
18
|
+
* never jumps.
|
|
19
|
+
*
|
|
20
|
+
* CLEARING RETURNS TO NOTHING SELECTED, NOT TO A WIDER LIST — and an earlier
|
|
21
|
+
* revision of this comment said the opposite, which is how a control came to be
|
|
22
|
+
* worded "show every relationship" while it emptied the panel. §17b makes the
|
|
23
|
+
* inspector a projection of the SELECTION, and `none` is a selection with no
|
|
24
|
+
* subject, so there is no list for it to widen to.
|
|
25
|
+
*
|
|
26
|
+
* The alternative was considered and not taken: `none` could list every
|
|
27
|
+
* relationship in the document, which would make the three states a clean
|
|
28
|
+
* narrowing — all, then one issue's, then one edge's — and make "show every
|
|
29
|
+
* relationship" literally true. It also invents a fourth thing for the panel to
|
|
30
|
+
* be, on a zone whose whole contract is that it shows what is selected. The
|
|
31
|
+
* cheaper repair was to stop the prose promising a behaviour the design does
|
|
32
|
+
* not have.
|
|
33
|
+
*
|
|
34
|
+
* ## Edge identity comes from `@issuegraph/core`
|
|
35
|
+
*
|
|
36
|
+
* A `ViewerEdge` carries no id — layer 1 has no need of one — but the picker,
|
|
37
|
+
* the overlays and the store all name edges by the identity `edgeIdentity`
|
|
38
|
+
* derives from content. Recomputing it here is composing the foundation both
|
|
39
|
+
* layers already sit on, which is the same crossing `picker/view.ts` declared
|
|
40
|
+
* and for the same reason: a local second spelling of an identity is how a host
|
|
41
|
+
* comes to hold two ids for one edge.
|
|
42
|
+
*/
|
|
43
|
+
import type { EdgeField } from '@issuegraph/core';
|
|
44
|
+
import type { ViewerDocument, ViewerHold, ViewerIssue } from '@issuegraph/viewer';
|
|
45
|
+
import type { WorkspaceSelection } from './selection.ts';
|
|
46
|
+
/** One relationship, as the inspector lists it. */
|
|
47
|
+
export interface InspectorRelationship {
|
|
48
|
+
/** The identity `@issuegraph/core` derives — what a retype or delete names. */
|
|
49
|
+
readonly edgeId: string;
|
|
50
|
+
readonly field: EdgeField;
|
|
51
|
+
readonly from: string;
|
|
52
|
+
readonly to: string;
|
|
53
|
+
/**
|
|
54
|
+
* Which end the subject is on — `null` when there is no direction to state.
|
|
55
|
+
*
|
|
56
|
+
* A DIRECTION RELATIVE TO THE SUBJECT, not a sentence: "blocked-by, outgoing"
|
|
57
|
+
* is a fact, and the English for it is the host's to write. The package
|
|
58
|
+
* refuses to construct one, exactly as the picker does.
|
|
59
|
+
*
|
|
60
|
+
* NULL FOR A SYMMETRIC FIELD, and that is a fact about the FORMAT rather
|
|
61
|
+
* than a rendering choice. `serialize-with` and `together-with` state the
|
|
62
|
+
* same relationship whichever way round their endpoints are stored —
|
|
63
|
+
* `edgeIdentity` normalizes them for exactly that reason — so a direction
|
|
64
|
+
* read off the stored order is one that does not exist, and a host wording
|
|
65
|
+
* it would describe the relationship wrongly. `picker/view.ts` already
|
|
66
|
+
* refuses a direction for those two kinds; this now agrees with it instead
|
|
67
|
+
* of contradicting it from the next zone over.
|
|
68
|
+
*
|
|
69
|
+
* Also `null` when the subject is not an issue: an edge selection has no
|
|
70
|
+
* "my end" to be relative to.
|
|
71
|
+
*/
|
|
72
|
+
readonly direction: 'outgoing' | 'incoming' | null;
|
|
73
|
+
}
|
|
74
|
+
/** What the inspector knows about the selected issue's position. */
|
|
75
|
+
export interface InspectorPosition {
|
|
76
|
+
/** 1-based, or `null` for a held slot — the viewer's own convention. */
|
|
77
|
+
readonly rank: number | null;
|
|
78
|
+
readonly ready: boolean;
|
|
79
|
+
readonly holds: readonly ViewerHold[];
|
|
80
|
+
}
|
|
81
|
+
export interface InspectorView {
|
|
82
|
+
/**
|
|
83
|
+
* What the selection resolved to.
|
|
84
|
+
*
|
|
85
|
+
* `none` covers both "nothing selected" and "the selection no longer
|
|
86
|
+
* resolves". They are deliberately one state rather than two: a selection
|
|
87
|
+
* that named a row a write has since removed is not an error a reader can
|
|
88
|
+
* act on, and rendering last frame's answer for it is the stale-detail bug
|
|
89
|
+
* that keeping no document on the selection exists to prevent.
|
|
90
|
+
*/
|
|
91
|
+
readonly subject: {
|
|
92
|
+
readonly kind: 'none';
|
|
93
|
+
} | {
|
|
94
|
+
readonly kind: 'issue';
|
|
95
|
+
readonly issue: ViewerIssue;
|
|
96
|
+
readonly position: InspectorPosition | null;
|
|
97
|
+
} | {
|
|
98
|
+
readonly kind: 'edge';
|
|
99
|
+
readonly relationship: InspectorRelationship;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* The relationships on show: every one touching the selected issue, the one
|
|
103
|
+
* selected edge, or none.
|
|
104
|
+
*/
|
|
105
|
+
readonly relationships: readonly InspectorRelationship[];
|
|
106
|
+
/** Whether an edge selection is narrowing the list. Drives the clear control. */
|
|
107
|
+
readonly filtered: boolean;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Project a document and a selection onto the inspector.
|
|
111
|
+
*
|
|
112
|
+
* Pure and total: an unresolvable selection returns the empty view rather than
|
|
113
|
+
* throwing, because a document changing under a selection is ordinary — a write
|
|
114
|
+
* lands, the order recomputes — and is not a condition a reader can fix.
|
|
115
|
+
*/
|
|
116
|
+
export declare function inspectorView(raw: ViewerDocument, selection: WorkspaceSelection): InspectorView;
|
|
117
|
+
//# sourceMappingURL=inspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector.d.ts","sourceRoot":"","sources":["../../src/workspace/inspector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAc,MAAM,oBAAoB,CAAC;AAG9F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,mDAAmD;AACnD,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAC,SAAS,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAAC;CACpD;AAED,oEAAoE;AACpE,MAAM,WAAW,iBAAiB;IAChC,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EACZ;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GACzB;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAA;KAAE,GACpG;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,EAAE,qBAAqB,CAAA;KAAE,CAAC;IAC5E;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACzD,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAkCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,kBAAkB,GAC5B,aAAa,CAmEf"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inspector: detail, the "why", relationships, and the edit affordances
|
|
3
|
+
* that hang off them.
|
|
4
|
+
*
|
|
5
|
+
* ## It is a projection of the selection, and holds no state of its own
|
|
6
|
+
*
|
|
7
|
+
* §17b makes `selected` the one edge state that also filters the inspector, so
|
|
8
|
+
* this zone is a pure function of the document and that single value. It keeps
|
|
9
|
+
* no "currently inspecting" of its own — a second copy would be free to
|
|
10
|
+
* disagree with the rail and the canvas about what is selected, which is the
|
|
11
|
+
* whole reason the workspace owns exactly one selection.
|
|
12
|
+
*
|
|
13
|
+
* ## An edge selection FILTERS; it does not open a different panel
|
|
14
|
+
*
|
|
15
|
+
* The distinction matters and it is easy to lose. With an edge selected the
|
|
16
|
+
* inspector shows the same relationship list, narrowed to that one edge —
|
|
17
|
+
* rather than a separate edge inspector. So the reader's frame of reference
|
|
18
|
+
* never jumps.
|
|
19
|
+
*
|
|
20
|
+
* CLEARING RETURNS TO NOTHING SELECTED, NOT TO A WIDER LIST — and an earlier
|
|
21
|
+
* revision of this comment said the opposite, which is how a control came to be
|
|
22
|
+
* worded "show every relationship" while it emptied the panel. §17b makes the
|
|
23
|
+
* inspector a projection of the SELECTION, and `none` is a selection with no
|
|
24
|
+
* subject, so there is no list for it to widen to.
|
|
25
|
+
*
|
|
26
|
+
* The alternative was considered and not taken: `none` could list every
|
|
27
|
+
* relationship in the document, which would make the three states a clean
|
|
28
|
+
* narrowing — all, then one issue's, then one edge's — and make "show every
|
|
29
|
+
* relationship" literally true. It also invents a fourth thing for the panel to
|
|
30
|
+
* be, on a zone whose whole contract is that it shows what is selected. The
|
|
31
|
+
* cheaper repair was to stop the prose promising a behaviour the design does
|
|
32
|
+
* not have.
|
|
33
|
+
*
|
|
34
|
+
* ## Edge identity comes from `@issuegraph/core`
|
|
35
|
+
*
|
|
36
|
+
* A `ViewerEdge` carries no id — layer 1 has no need of one — but the picker,
|
|
37
|
+
* the overlays and the store all name edges by the identity `edgeIdentity`
|
|
38
|
+
* derives from content. Recomputing it here is composing the foundation both
|
|
39
|
+
* layers already sit on, which is the same crossing `picker/view.ts` declared
|
|
40
|
+
* and for the same reason: a local second spelling of an identity is how a host
|
|
41
|
+
* comes to hold two ids for one edge.
|
|
42
|
+
*/
|
|
43
|
+
import { edgeIdentity, isSymmetricEdgeField } from '@issuegraph/core';
|
|
44
|
+
import { normalizeDocument } from '@issuegraph/viewer';
|
|
45
|
+
const EMPTY = {
|
|
46
|
+
subject: { kind: 'none' },
|
|
47
|
+
relationships: [],
|
|
48
|
+
filtered: false,
|
|
49
|
+
};
|
|
50
|
+
/** Every relationship in the document, carrying the identity edits name. */
|
|
51
|
+
function relationshipsOf(document, subject) {
|
|
52
|
+
return document.edges.map((edge) => ({
|
|
53
|
+
edgeId: edgeIdentity(edge.field, edge.from, edge.to),
|
|
54
|
+
field: edge.field,
|
|
55
|
+
from: edge.from,
|
|
56
|
+
to: edge.to,
|
|
57
|
+
direction: subject === null ||
|
|
58
|
+
isSymmetricEdgeField(edge.field) ||
|
|
59
|
+
(edge.from !== subject && edge.to !== subject)
|
|
60
|
+
? null
|
|
61
|
+
: edge.from === subject
|
|
62
|
+
? 'outgoing'
|
|
63
|
+
: 'incoming',
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
/** The slot carrying a key, if the order places it. */
|
|
67
|
+
function slotFor(document, key) {
|
|
68
|
+
return document.order.slots.find((slot) => slot.members.includes(key));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Project a document and a selection onto the inspector.
|
|
72
|
+
*
|
|
73
|
+
* Pure and total: an unresolvable selection returns the empty view rather than
|
|
74
|
+
* throwing, because a document changing under a selection is ordinary — a write
|
|
75
|
+
* lands, the order recomputes — and is not a condition a reader can fix.
|
|
76
|
+
*/
|
|
77
|
+
export function inspectorView(raw, selection) {
|
|
78
|
+
if (selection.kind === 'none')
|
|
79
|
+
return EMPTY;
|
|
80
|
+
// IT NORMALIZES ITS OWN INPUT, so the list can never disagree with what the
|
|
81
|
+
// other zones drew. Reading the raw edges published relationships layer 1 had
|
|
82
|
+
// already dropped — a dangling edge, a repeated one, a self-edge — each with
|
|
83
|
+
// a live `select-edge` command on it, so the inspector offered the reader an
|
|
84
|
+
// edge that exists on no other surface.
|
|
85
|
+
//
|
|
86
|
+
// Inside rather than at the call site, because this is exported: a host
|
|
87
|
+
// calling it directly gets the same answer the workspace does. Idempotent, so
|
|
88
|
+
// the workspace normalizing first costs a pass and changes nothing.
|
|
89
|
+
const document = normalizeDocument(raw).document;
|
|
90
|
+
if (selection.kind === 'issue') {
|
|
91
|
+
// CANONICALIZED TO THE SLOT LEAD, because a together unit is ONE row and
|
|
92
|
+
// layer 1 has already decided which member speaks for it. `ViewerSlot.lead`
|
|
93
|
+
// is documented as "the detail surface's subject", and both projections run
|
|
94
|
+
// their options through `atStations` before drawing — so a selection naming
|
|
95
|
+
// a PARTNER marked the lead current in the rail and on the canvas while this
|
|
96
|
+
// panel showed the partner's title and relationships. Two zones naming
|
|
97
|
+
// different issues for one selection, which is the exact thing holding a
|
|
98
|
+
// single selection value was supposed to make impossible.
|
|
99
|
+
//
|
|
100
|
+
// Falls back to the key itself when the order does not place it: an
|
|
101
|
+
// excluded or unplaced issue is its own subject, and there is no lead to
|
|
102
|
+
// defer to.
|
|
103
|
+
const placement = slotFor(document, selection.key);
|
|
104
|
+
const subject = placement?.lead ?? selection.key;
|
|
105
|
+
const issue = document.issues.find((candidate) => candidate.key === subject);
|
|
106
|
+
if (issue === undefined)
|
|
107
|
+
return EMPTY;
|
|
108
|
+
const slot = placement;
|
|
109
|
+
return {
|
|
110
|
+
subject: {
|
|
111
|
+
kind: 'issue',
|
|
112
|
+
issue,
|
|
113
|
+
// NULL RATHER THAN A FABRICATED POSITION. An issue the order excludes —
|
|
114
|
+
// a duplicate — genuinely has no position, and inventing `rank: null,
|
|
115
|
+
// ready: false` for it would read as a hold, which is a different fact
|
|
116
|
+
// with a different remedy.
|
|
117
|
+
position: slot === undefined
|
|
118
|
+
? null
|
|
119
|
+
: { rank: slot.rank, ready: slot.ready, holds: slot.holds },
|
|
120
|
+
},
|
|
121
|
+
// FILTERED ON MEMBERSHIP, NOT ON DIRECTION. Those were the same question
|
|
122
|
+
// only while every edge touching the subject had one — and the moment a
|
|
123
|
+
// symmetric field correctly reported `null`, a `together-with` or
|
|
124
|
+
// `serialize-with` on the selected issue disappeared from the panel
|
|
125
|
+
// entirely. "Does this edge touch my subject" and "which end is my
|
|
126
|
+
// subject on" are different questions, and only the first belongs here.
|
|
127
|
+
relationships: relationshipsOf(document, subject).filter((relationship) => relationship.from === subject || relationship.to === subject),
|
|
128
|
+
filtered: false,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const relationship = relationshipsOf(document, null).find((candidate) => candidate.edgeId === selection.edgeId);
|
|
132
|
+
if (relationship === undefined)
|
|
133
|
+
return EMPTY;
|
|
134
|
+
return {
|
|
135
|
+
subject: { kind: 'edge', relationship },
|
|
136
|
+
relationships: [relationship],
|
|
137
|
+
filtered: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=inspector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspector.js","sourceRoot":"","sources":["../../src/workspace/inspector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The order rail: always present, always complete, and virtualised.
|
|
3
|
+
*
|
|
4
|
+
* ## The asymmetry with the canvas is the design, not an inconsistency
|
|
5
|
+
*
|
|
6
|
+
* §17f gives the two centre zones opposite obligations. The canvas answers
|
|
7
|
+
* "what surrounds this issue" and REFUSES above its budget — that is #10343's
|
|
8
|
+
* scale ladder, and it is correct. The rail answers "what gets worked next" for
|
|
9
|
+
* the whole backlog and must NEVER refuse. Assembling them must not average the
|
|
10
|
+
* two: a rail that paginates has stopped answering its question, and a canvas
|
|
11
|
+
* that tries to keep up with the rail has stopped honouring its budget.
|
|
12
|
+
*
|
|
13
|
+
* So virtualisation here is a requirement rather than an optimisation, and it
|
|
14
|
+
* is the resolution of what reads at first like a contradiction — "complete"
|
|
15
|
+
* and "windowed" at once.
|
|
16
|
+
*
|
|
17
|
+
* **The MODEL is complete; the WINDOW is bounded.** Every slot the host handed
|
|
18
|
+
* over is held, and {@link RailWindow.addressOf} answers for every rank in the
|
|
19
|
+
* order whether or not it is drawn. What is bounded is only how many rows are
|
|
20
|
+
* rendered at a time. Nothing is dropped, nothing is refused, and a host that
|
|
21
|
+
* scrolls asks for a different window over the same complete model.
|
|
22
|
+
*
|
|
23
|
+
* That is what "every rank is addressable" means, and it is the property the
|
|
24
|
+
* acceptance suite drives at 312 rows.
|
|
25
|
+
*
|
|
26
|
+
* ## `addressOf` is a closure over a private index
|
|
27
|
+
*
|
|
28
|
+
* The same shape — and the same reasoning — as `AuditOverlay.rowFor`. Handing
|
|
29
|
+
* out the index itself would let a JavaScript consumer mutate it, after which
|
|
30
|
+
* the lookups and `total` would disagree about what the order contains, which
|
|
31
|
+
* is the inconsistency this value exists to prevent. A closure cannot be
|
|
32
|
+
* reached at all, and still answers in constant time.
|
|
33
|
+
*
|
|
34
|
+
* ## What gets windowed
|
|
35
|
+
*
|
|
36
|
+
* Slots are sliced, and the issues and edges are cut down to exactly what the
|
|
37
|
+
* drawn rows need — a drawn slot's members, an exclusion's key, and the
|
|
38
|
+
* endpoints of any edge a drawn row owes a badge for.
|
|
39
|
+
*
|
|
40
|
+
* KEEPING THE WHOLE ISSUE LIST WAS THE OBVIOUS THING AND IT WAS WRONG. See the
|
|
41
|
+
* note at the filter itself for what it cost: the linear projection renders a
|
|
42
|
+
* count of the keys that appear in no slot and on no edge, so every edgeless
|
|
43
|
+
* issue outside the window was reported to the reader as isolated — the rail
|
|
44
|
+
* describing the reader's scroll position as though it were the document.
|
|
45
|
+
*
|
|
46
|
+
* `together-with` keeps its own rule, and it is layer 1's rather than a choice
|
|
47
|
+
* made here: that edge draws as an ENCLOSURE around one slot's members, so the
|
|
48
|
+
* viewer drops — and reports — any whose members no longer share a drawn slot.
|
|
49
|
+
* Those edges are left out of the windowed document and counted on
|
|
50
|
+
* {@link RailWindow.undrawn} instead, so the fact is reported as a property of
|
|
51
|
+
* the WINDOW rather than leaking out as a document defect.
|
|
52
|
+
*/
|
|
53
|
+
import type { ViewerDocument, ViewerSlot } from '@issuegraph/viewer';
|
|
54
|
+
/**
|
|
55
|
+
* How many rows a window holds when the host does not say.
|
|
56
|
+
*
|
|
57
|
+
* A round number rather than a measured one: this package has no mount and
|
|
58
|
+
* therefore no viewport to measure, so any default here is a guess. It is
|
|
59
|
+
* published so a host can see what it is overriding, and generous enough that
|
|
60
|
+
* a first paint fills an ordinary screen.
|
|
61
|
+
*/
|
|
62
|
+
export declare const RAIL_WINDOW = 50;
|
|
63
|
+
export interface RailWindowOptions {
|
|
64
|
+
/**
|
|
65
|
+
* The first row to draw, as a 0-BASED offset into the order's slots.
|
|
66
|
+
*
|
|
67
|
+
* An offset, deliberately, and not a rank: a held slot has `rank === null`,
|
|
68
|
+
* so ranks are not a coordinate you can slice on. Out-of-range values are
|
|
69
|
+
* clamped rather than refused — a host that scrolls past the end gets the
|
|
70
|
+
* last window, which is what a scroll container does anyway.
|
|
71
|
+
*/
|
|
72
|
+
readonly start?: number | undefined;
|
|
73
|
+
/** How many rows to draw. Defaults to {@link RAIL_WINDOW}. */
|
|
74
|
+
readonly count?: number | undefined;
|
|
75
|
+
}
|
|
76
|
+
export interface RailWindow {
|
|
77
|
+
/** Every slot in the order, drawn or not. The completeness claim, as a number. */
|
|
78
|
+
readonly total: number;
|
|
79
|
+
/** The 0-based offset of the first drawn row, after clamping. */
|
|
80
|
+
readonly start: number;
|
|
81
|
+
/** How many rows are drawn. Fewer than asked for at the end of the order. */
|
|
82
|
+
readonly count: number;
|
|
83
|
+
/** Slots before the window. A host sizes its leading spacer from this. */
|
|
84
|
+
readonly before: number;
|
|
85
|
+
/** Slots after the window. A host sizes its trailing spacer from this. */
|
|
86
|
+
readonly after: number;
|
|
87
|
+
/** The drawn slots, in order. */
|
|
88
|
+
readonly rows: readonly ViewerSlot[];
|
|
89
|
+
/** The document to hand the viewer: the windowed slots, and what they need. */
|
|
90
|
+
readonly document: ViewerDocument;
|
|
91
|
+
/**
|
|
92
|
+
* `together-with` edges left out because their unit is outside the window.
|
|
93
|
+
*
|
|
94
|
+
* Reported rather than silent: it is the one thing windowing costs, and a
|
|
95
|
+
* host drawing a connector count of its own needs to know the window is not
|
|
96
|
+
* the whole story.
|
|
97
|
+
*/
|
|
98
|
+
readonly undrawn: number;
|
|
99
|
+
/**
|
|
100
|
+
* The slot at a rank — ANY rank in the order, drawn or not.
|
|
101
|
+
*
|
|
102
|
+
* This is the completeness property, and it is why the rail can be windowed
|
|
103
|
+
* without ceasing to answer its question: a reader asking "what is at 287?"
|
|
104
|
+
* gets an answer from a rail showing rows 1–50.
|
|
105
|
+
*
|
|
106
|
+
* Ranks are 1-BASED, matching what the rail renders and what a reader sees.
|
|
107
|
+
* A held slot has no rank at all and is unreachable this way by construction
|
|
108
|
+
* — it has no position in the sequence, which is precisely what `rank: null`
|
|
109
|
+
* says.
|
|
110
|
+
*/
|
|
111
|
+
readonly addressOf: (rank: number) => ViewerSlot | undefined;
|
|
112
|
+
/** The 0-based offset of a slot's lead key, for a host scrolling to it. */
|
|
113
|
+
readonly offsetOf: (key: string) => number | undefined;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Window an order without narrowing it.
|
|
117
|
+
*
|
|
118
|
+
* Pure, and total over any document: there is no input that makes this throw or
|
|
119
|
+
* refuse, because the rail is the zone that is not allowed to.
|
|
120
|
+
*/
|
|
121
|
+
export declare function railWindow(raw: ViewerDocument, options?: RailWindowOptions): RailWindow;
|
|
122
|
+
//# sourceMappingURL=rail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../src/workspace/rail.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrE;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,KAAK,CAAC;AAE9B,MAAM,WAAW,iBAAiB;IAChC;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,UAAU,EAAE,CAAC;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAC;IAC7D,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACxD;AA4BD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,cAAc,EACnB,OAAO,GAAE,iBAAsB,GAC9B,UAAU,CAgIZ"}
|