@issuegraph/editor 0.2.0 → 0.3.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 +31 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/overlay/projected.d.ts +21 -0
- package/dist/overlay/projected.d.ts.map +1 -0
- package/dist/overlay/projected.js +49 -0
- package/dist/overlay/projected.js.map +1 -0
- package/dist/scale/render.d.ts +19 -0
- package/dist/scale/render.d.ts.map +1 -1
- package/dist/scale/render.js +10 -29
- package/dist/scale/render.js.map +1 -1
- package/dist/workspace/chrome.d.ts +21 -0
- package/dist/workspace/chrome.d.ts.map +1 -0
- package/dist/workspace/chrome.js +178 -0
- package/dist/workspace/chrome.js.map +1 -0
- package/dist/workspace/host.d.ts +148 -0
- package/dist/workspace/host.d.ts.map +1 -0
- package/dist/workspace/host.js +316 -0
- package/dist/workspace/host.js.map +1 -0
- package/dist/workspace/mount.d.ts +139 -0
- package/dist/workspace/mount.d.ts.map +1 -0
- package/dist/workspace/mount.js +882 -0
- package/dist/workspace/mount.js.map +1 -0
- package/dist/workspace/render.d.ts +7 -0
- package/dist/workspace/render.d.ts.map +1 -1
- package/dist/workspace/render.js +1 -0
- package/dist/workspace/render.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace's host reducer — every decision a mount makes, with no DOM.
|
|
3
|
+
*
|
|
4
|
+
* `renderWorkspace` renders and publishes: each control says what it does as
|
|
5
|
+
* `data-ig-command`, and the viewer publishes its two identities, `data-ig-key`
|
|
6
|
+
* and `data-ig-group`. This file is the DECISIONS a mount takes on reading
|
|
7
|
+
* them. The shell in `mount.ts` reads the DOM and turns what it saw into a
|
|
8
|
+
* {@link HostCommand}; this file turns the command into the next state and a
|
|
9
|
+
* list of {@link HostEffect}s the shell then performs against the store.
|
|
10
|
+
*
|
|
11
|
+
* It composes the package's own reducers — `selectionReducer`, `scaleReducer`,
|
|
12
|
+
* `createReducer`, `pickerView` — and adds only what those leave to a mount:
|
|
13
|
+
* which one selection is shared, when the create draft begins and ends, the
|
|
14
|
+
* rail's scroll offset, and the drag that turns a canvas drop into a draft.
|
|
15
|
+
* Nothing here reaches a node, so all of it runs under `node --test` with no
|
|
16
|
+
* DOM, which is the property the package's other reducers are shaped for and
|
|
17
|
+
* the reason this is not written into listeners.
|
|
18
|
+
*
|
|
19
|
+
* ## Lifted from the demo, and why
|
|
20
|
+
*
|
|
21
|
+
* This was the demo's `host.ts`, written once for that page. A second host
|
|
22
|
+
* re-implemented it from scratch and re-ran the review rounds that shaped it;
|
|
23
|
+
* the design kit's layer rule puts the interaction shell in layer 2, not in
|
|
24
|
+
* the host. What stayed behind in the demo is exactly what was demo-shaped:
|
|
25
|
+
* the theme switch, the armed dispatch outcome, and the sandbox reset — none
|
|
26
|
+
* of which a host reducer should know about, and each of which the demo now
|
|
27
|
+
* handles beside the mount rather than through it.
|
|
28
|
+
*/
|
|
29
|
+
import { type EdgeField } from '@issuegraph/core';
|
|
30
|
+
import type { GraphDocument, MutationId, Proposal, StoredIssue } from '@issuegraph/store';
|
|
31
|
+
import { type CreateDraft } from '../create/draft.ts';
|
|
32
|
+
import type { KeyIntent } from '../create/keys.ts';
|
|
33
|
+
import type { Point } from '../create/placement.ts';
|
|
34
|
+
import { type ScaleState } from '../scale/commands.ts';
|
|
35
|
+
import { type WorkspaceSelection } from './selection.ts';
|
|
36
|
+
export interface HostState {
|
|
37
|
+
readonly selection: WorkspaceSelection;
|
|
38
|
+
readonly scale: ScaleState;
|
|
39
|
+
readonly auditFiltered: boolean;
|
|
40
|
+
/** The rail window's first slot — a scroll offset in rows, never a rank. */
|
|
41
|
+
readonly railStart: number;
|
|
42
|
+
readonly draft: CreateDraft;
|
|
43
|
+
/** What the reader has typed into the target search. */
|
|
44
|
+
readonly targetQuery: string;
|
|
45
|
+
/** The issue a canvas drag started on, while the pointer is down. */
|
|
46
|
+
readonly drag: string | null;
|
|
47
|
+
/** Where a canvas drop landed, so the kind chooser can be placed there. */
|
|
48
|
+
readonly drop: Point | null;
|
|
49
|
+
}
|
|
50
|
+
export declare const INITIAL_HOST_STATE: HostState;
|
|
51
|
+
/**
|
|
52
|
+
* What the shell saw.
|
|
53
|
+
*
|
|
54
|
+
* `control` carries a `data-ig-command` — the package's own vocabulary
|
|
55
|
+
* (`select-edge`, `focus`, `search`, `retype`, `flip`, …) and the mount's
|
|
56
|
+
* chrome (`add`, `kind`, `target`, `delete`, `retry`, …) share one channel
|
|
57
|
+
* because the shell reads one attribute. `point` and `group` are the viewer's
|
|
58
|
+
* two identities: a focusable issue key, and a mark naming an edge or a slot.
|
|
59
|
+
*/
|
|
60
|
+
export type HostCommand = {
|
|
61
|
+
readonly kind: 'point';
|
|
62
|
+
readonly key: string;
|
|
63
|
+
} | {
|
|
64
|
+
readonly kind: 'group';
|
|
65
|
+
readonly id: string;
|
|
66
|
+
} | {
|
|
67
|
+
readonly kind: 'control';
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly target?: string | undefined;
|
|
70
|
+
readonly value?: string | undefined;
|
|
71
|
+
} | {
|
|
72
|
+
readonly kind: 'intent';
|
|
73
|
+
readonly intent: KeyIntent;
|
|
74
|
+
} | {
|
|
75
|
+
readonly kind: 'scroll';
|
|
76
|
+
readonly start: number;
|
|
77
|
+
} | {
|
|
78
|
+
readonly kind: 'drag-start';
|
|
79
|
+
readonly key: string;
|
|
80
|
+
} | {
|
|
81
|
+
readonly kind: 'drop';
|
|
82
|
+
readonly key: string | null;
|
|
83
|
+
readonly at: Point;
|
|
84
|
+
};
|
|
85
|
+
/** What the shell performs against the store after reducing. */
|
|
86
|
+
export type HostEffect = {
|
|
87
|
+
readonly kind: 'propose';
|
|
88
|
+
readonly proposal: Proposal;
|
|
89
|
+
} | {
|
|
90
|
+
readonly kind: 'retry';
|
|
91
|
+
readonly mutationId: MutationId;
|
|
92
|
+
} | {
|
|
93
|
+
readonly kind: 'discard';
|
|
94
|
+
readonly mutationId: MutationId;
|
|
95
|
+
} | {
|
|
96
|
+
readonly kind: 'dismiss-change';
|
|
97
|
+
};
|
|
98
|
+
export interface HostResult {
|
|
99
|
+
readonly state: HostState;
|
|
100
|
+
readonly effects: readonly HostEffect[];
|
|
101
|
+
}
|
|
102
|
+
/** The one reducer. `document` is the landed document, for edge lookups. */
|
|
103
|
+
export declare function reduceHost(state: HostState, command: HostCommand, document: GraphDocument): HostResult;
|
|
104
|
+
/**
|
|
105
|
+
* Bring the state back into agreement with a document that moved under it.
|
|
106
|
+
*
|
|
107
|
+
* The store re-renders on every landed write, and a write can remove what the
|
|
108
|
+
* state names: a retype or a flip gives the edge a NEW identity, a delete
|
|
109
|
+
* removes it, and a conflict's rehydrate can drop an issue a draft was aimed
|
|
110
|
+
* at. A selection naming an edge the document no longer carries would leave
|
|
111
|
+
* the inspector showing a picker for nothing — the viewer already refuses a
|
|
112
|
+
* stale selection the same way, so the host does too, from the document
|
|
113
|
+
* rather than from memory of what it just proposed.
|
|
114
|
+
*/
|
|
115
|
+
export declare function reconcileHost(state: HostState, document: GraphDocument): HostState;
|
|
116
|
+
/** The issues a target search offers, by reference or title, never the source itself. */
|
|
117
|
+
export declare function targetMatches(issues: readonly StoredIssue[], query: string, source: string | null, limit?: number): readonly StoredIssue[];
|
|
118
|
+
/** The edge kinds, in the format's order — the keyboard path's `1`–`5` is this list. */
|
|
119
|
+
export declare const KINDS: readonly EdgeField[];
|
|
120
|
+
/** How far the reader may scroll into the rail window before it is re-cut around them, in rows. */
|
|
121
|
+
export declare const RAIL_SLACK = 20;
|
|
122
|
+
/**
|
|
123
|
+
* The slack a window of `count` rows actually gets: `RAIL_SLACK`, bounded to a
|
|
124
|
+
* quarter of the window and never below one row. A slack as wide as the window
|
|
125
|
+
* re-cut a small window onto its own start — ArrowDown on the last drawn row
|
|
126
|
+
* computed `offset - slack` at or below the current start, dispatched it
|
|
127
|
+
* unchanged, and keyboard navigation could not leave the first window.
|
|
128
|
+
*/
|
|
129
|
+
export declare function railSlackFor(count: number): number;
|
|
130
|
+
/**
|
|
131
|
+
* Where the rail window should be re-cut for a scroll position, or `null` when
|
|
132
|
+
* it should stay where it is.
|
|
133
|
+
*
|
|
134
|
+
* `row` is the first visible row (scroll offset over pitch), `start` the
|
|
135
|
+
* window's current first slot, `count` the window's size and `total` the rows
|
|
136
|
+
* in the order. Inside the window's slack band nothing moves. Outside it, the
|
|
137
|
+
* window is re-cut `RAIL_SLACK` rows above the reader, clamped to the order.
|
|
138
|
+
*
|
|
139
|
+
* THE CLAMP CAN LAND ON THE CURRENT START, AND THAT CASE MUST ANSWER `null`.
|
|
140
|
+
* At the end of a long order the window is already pinned to its last start
|
|
141
|
+
* while the reader is deep inside it, so every scroll position there is
|
|
142
|
+
* "outside the band" and clamps back to the same start. A shell that
|
|
143
|
+
* dispatched that as a change redrew, restored the scroll offset — which
|
|
144
|
+
* fires `scroll` again — and never stopped. The decision is a pure function
|
|
145
|
+
* here so that cycle is refused where it can be tested without a browser.
|
|
146
|
+
*/
|
|
147
|
+
export declare function railWindowTarget(row: number, start: number, count: number, total: number): number | null;
|
|
148
|
+
//# sourceMappingURL=host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/workspace/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace's host reducer — every decision a mount makes, with no DOM.
|
|
3
|
+
*
|
|
4
|
+
* `renderWorkspace` renders and publishes: each control says what it does as
|
|
5
|
+
* `data-ig-command`, and the viewer publishes its two identities, `data-ig-key`
|
|
6
|
+
* and `data-ig-group`. This file is the DECISIONS a mount takes on reading
|
|
7
|
+
* them. The shell in `mount.ts` reads the DOM and turns what it saw into a
|
|
8
|
+
* {@link HostCommand}; this file turns the command into the next state and a
|
|
9
|
+
* list of {@link HostEffect}s the shell then performs against the store.
|
|
10
|
+
*
|
|
11
|
+
* It composes the package's own reducers — `selectionReducer`, `scaleReducer`,
|
|
12
|
+
* `createReducer`, `pickerView` — and adds only what those leave to a mount:
|
|
13
|
+
* which one selection is shared, when the create draft begins and ends, the
|
|
14
|
+
* rail's scroll offset, and the drag that turns a canvas drop into a draft.
|
|
15
|
+
* Nothing here reaches a node, so all of it runs under `node --test` with no
|
|
16
|
+
* DOM, which is the property the package's other reducers are shaped for and
|
|
17
|
+
* the reason this is not written into listeners.
|
|
18
|
+
*
|
|
19
|
+
* ## Lifted from the demo, and why
|
|
20
|
+
*
|
|
21
|
+
* This was the demo's `host.ts`, written once for that page. A second host
|
|
22
|
+
* re-implemented it from scratch and re-ran the review rounds that shaped it;
|
|
23
|
+
* the design kit's layer rule puts the interaction shell in layer 2, not in
|
|
24
|
+
* the host. What stayed behind in the demo is exactly what was demo-shaped:
|
|
25
|
+
* the theme switch, the armed dispatch outcome, and the sandbox reset — none
|
|
26
|
+
* of which a host reducer should know about, and each of which the demo now
|
|
27
|
+
* handles beside the mount rather than through it.
|
|
28
|
+
*/
|
|
29
|
+
import { EDGE_FIELDS, isEdgeField } from '@issuegraph/core';
|
|
30
|
+
import { findEdge } from '@issuegraph/store';
|
|
31
|
+
import { IDLE_CREATE_DRAFT, createReducer } from "../create/draft.js";
|
|
32
|
+
import { pickerView } from "../picker/view.js";
|
|
33
|
+
import { INITIAL_SCALE_STATE, scaleReducer } from "../scale/commands.js";
|
|
34
|
+
import { INITIAL_SELECTION, selectedEdgeId, selectedKey, selectionReducer, } from "./selection.js";
|
|
35
|
+
export const INITIAL_HOST_STATE = Object.freeze({
|
|
36
|
+
selection: INITIAL_SELECTION,
|
|
37
|
+
scale: INITIAL_SCALE_STATE,
|
|
38
|
+
auditFiltered: false,
|
|
39
|
+
railStart: 0,
|
|
40
|
+
draft: IDLE_CREATE_DRAFT,
|
|
41
|
+
targetQuery: '',
|
|
42
|
+
drag: null,
|
|
43
|
+
drop: null,
|
|
44
|
+
});
|
|
45
|
+
function settled(state) {
|
|
46
|
+
return { state, effects: [] };
|
|
47
|
+
}
|
|
48
|
+
/** A draft step: apply the create reducer, and emit the proposal it completes. */
|
|
49
|
+
function drafted(state, command) {
|
|
50
|
+
const result = createReducer(state.draft, command);
|
|
51
|
+
if (result.proposal === null) {
|
|
52
|
+
// BEGINNING A DRAFT SELECTS ITS SOURCE. The inspector draws the picker for
|
|
53
|
+
// a selected edge ahead of any draft, so a draft begun by R from a focused
|
|
54
|
+
// row while an edge stayed selected would render behind the picker and
|
|
55
|
+
// could never reach its target search. One selection, and it is the
|
|
56
|
+
// draft's subject — the same rule the canvas drop already applies.
|
|
57
|
+
const selection = command.kind === 'begin' ? { kind: 'issue', key: command.source } : state.selection;
|
|
58
|
+
// A CANCEL CLEARS THE DRAFT'S CHROME TOO — the drop point a canvas chooser
|
|
59
|
+
// was placed at and the query typed into the target search — exactly as
|
|
60
|
+
// the explicit cancel control does. Escape reaches here through the key
|
|
61
|
+
// map, and a draft begun afterwards must not open at the old drop point
|
|
62
|
+
// or with the old query already in the box.
|
|
63
|
+
const chrome = command.kind === 'cancel' ? { targetQuery: '', drop: null } : {};
|
|
64
|
+
return settled({ ...state, draft: result.draft, selection, ...chrome });
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
state: { ...state, draft: IDLE_CREATE_DRAFT, targetQuery: '', drop: null },
|
|
68
|
+
effects: [{ kind: 'propose', proposal: result.proposal }],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** A pointer on an issue: a target while one is being chosen, a selection otherwise. */
|
|
72
|
+
function pointed(state, key) {
|
|
73
|
+
const choosingTarget = state.draft.kind !== null && state.draft.target === null;
|
|
74
|
+
if (choosingTarget && key !== state.draft.source) {
|
|
75
|
+
return drafted(state, { kind: 'target', ref: key });
|
|
76
|
+
}
|
|
77
|
+
return settled({
|
|
78
|
+
...state,
|
|
79
|
+
selection: selectionReducer(state.selection, { kind: 'select-issue', key }),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function selectEdge(state, edgeId) {
|
|
83
|
+
return settled({
|
|
84
|
+
...state,
|
|
85
|
+
selection: selectionReducer(state.selection, { kind: 'select-edge', edgeId }),
|
|
86
|
+
draft: IDLE_CREATE_DRAFT,
|
|
87
|
+
targetQuery: '',
|
|
88
|
+
drop: null,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/** The retype and flip proposals come from the picker's own view, never built here. */
|
|
92
|
+
function pickerProposal(document, edgeId, choice) {
|
|
93
|
+
const view = pickerView(document, edgeId);
|
|
94
|
+
if (choice.kind === 'flip')
|
|
95
|
+
return view.flip?.proposal ?? null;
|
|
96
|
+
return view.options.find((option) => option.kind === choice.field && !option.current)?.proposal ?? null;
|
|
97
|
+
}
|
|
98
|
+
function controlled(state, name, target, value, document) {
|
|
99
|
+
const edgeId = selectedEdgeId(state.selection);
|
|
100
|
+
switch (name) {
|
|
101
|
+
// --- the package's own commands ---
|
|
102
|
+
case 'select-edge':
|
|
103
|
+
return target === undefined ? settled(state) : selectEdge(state, target);
|
|
104
|
+
case 'select-issue':
|
|
105
|
+
// THE HOLDER DEEP LINK. The inspector publishes a hold's subject — the
|
|
106
|
+
// open blocker, the claimed peer — as this control, so a reader can reach
|
|
107
|
+
// the issue holding the one they are looking at. It is a pointer on that
|
|
108
|
+
// issue, with a pointer's rules: a selection, or the target of a draft.
|
|
109
|
+
return target === undefined ? settled(state) : pointed(state, target);
|
|
110
|
+
case 'clear':
|
|
111
|
+
return settled({
|
|
112
|
+
...state,
|
|
113
|
+
selection: INITIAL_SELECTION,
|
|
114
|
+
draft: IDLE_CREATE_DRAFT,
|
|
115
|
+
targetQuery: '',
|
|
116
|
+
drop: null,
|
|
117
|
+
});
|
|
118
|
+
case 'focus':
|
|
119
|
+
return target === undefined
|
|
120
|
+
? settled(state)
|
|
121
|
+
: settled({ ...state, scale: scaleReducer(state.scale, { kind: 'focus', key: target }) });
|
|
122
|
+
case 'clear-focus':
|
|
123
|
+
return settled({ ...state, scale: scaleReducer(state.scale, { kind: 'clear-focus' }) });
|
|
124
|
+
case 'search':
|
|
125
|
+
return settled({
|
|
126
|
+
...state,
|
|
127
|
+
scale: scaleReducer(state.scale, { kind: 'search', query: value ?? '' }),
|
|
128
|
+
});
|
|
129
|
+
case 'open-isolated':
|
|
130
|
+
return settled({ ...state, scale: scaleReducer(state.scale, { kind: 'open-isolated' }) });
|
|
131
|
+
case 'close-isolated':
|
|
132
|
+
return settled({ ...state, scale: scaleReducer(state.scale, { kind: 'close-isolated' }) });
|
|
133
|
+
case 'retype': {
|
|
134
|
+
if (edgeId === null || value === undefined || !isEdgeField(value))
|
|
135
|
+
return settled(state);
|
|
136
|
+
const proposal = pickerProposal(document, edgeId, { kind: 'retype', field: value });
|
|
137
|
+
return proposal === null ? settled(state) : { state, effects: [{ kind: 'propose', proposal }] };
|
|
138
|
+
}
|
|
139
|
+
case 'flip': {
|
|
140
|
+
if (edgeId === null)
|
|
141
|
+
return settled(state);
|
|
142
|
+
const proposal = pickerProposal(document, edgeId, { kind: 'flip' });
|
|
143
|
+
return proposal === null ? settled(state) : { state, effects: [{ kind: 'propose', proposal }] };
|
|
144
|
+
}
|
|
145
|
+
case 'dismiss-change':
|
|
146
|
+
return { state, effects: [{ kind: 'dismiss-change' }] };
|
|
147
|
+
// --- the mount's chrome ---
|
|
148
|
+
case 'audit-filter':
|
|
149
|
+
return settled({ ...state, auditFiltered: !state.auditFiltered });
|
|
150
|
+
case 'add': {
|
|
151
|
+
const source = selectedKey(state.selection);
|
|
152
|
+
return source === null ? settled(state) : drafted(state, { kind: 'begin', source });
|
|
153
|
+
}
|
|
154
|
+
case 'kind':
|
|
155
|
+
return value === undefined || !isEdgeField(value)
|
|
156
|
+
? settled(state)
|
|
157
|
+
: drafted(state, { kind: 'type', edgeKind: value });
|
|
158
|
+
case 'target-query':
|
|
159
|
+
return settled({ ...state, targetQuery: value ?? '' });
|
|
160
|
+
case 'target':
|
|
161
|
+
return target === undefined ? settled(state) : drafted(state, { kind: 'target', ref: target });
|
|
162
|
+
case 'cancel':
|
|
163
|
+
return settled({ ...state, draft: IDLE_CREATE_DRAFT, targetQuery: '', drop: null });
|
|
164
|
+
case 'delete':
|
|
165
|
+
return edgeId === null
|
|
166
|
+
? settled(state)
|
|
167
|
+
: { state, effects: [{ kind: 'propose', proposal: { op: 'delete', edgeId } }] };
|
|
168
|
+
case 'retry':
|
|
169
|
+
return target === undefined ? settled(state) : { state, effects: [{ kind: 'retry', mutationId: target }] };
|
|
170
|
+
case 'discard':
|
|
171
|
+
return target === undefined
|
|
172
|
+
? settled(state)
|
|
173
|
+
: { state, effects: [{ kind: 'discard', mutationId: target }] };
|
|
174
|
+
default:
|
|
175
|
+
// A COMMAND THIS REDUCER DOES NOT KNOW CHANGES NOTHING. A host's own
|
|
176
|
+
// chrome may publish commands on the same attribute — the demo's theme
|
|
177
|
+
// switch does — and those are the host's to read from its own listener,
|
|
178
|
+
// never a reason for this reducer to guess.
|
|
179
|
+
return settled(state);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function intended(state, intent) {
|
|
183
|
+
switch (intent.kind) {
|
|
184
|
+
case 'none':
|
|
185
|
+
// `T` opens the picker; the picker is already drawn whenever an edge is
|
|
186
|
+
// selected, so there is nothing to change.
|
|
187
|
+
case 'retype':
|
|
188
|
+
return settled(state);
|
|
189
|
+
case 'create':
|
|
190
|
+
return drafted(state, intent.command);
|
|
191
|
+
case 'propose':
|
|
192
|
+
return { state, effects: [{ kind: 'propose', proposal: intent.proposal }] };
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** The one reducer. `document` is the landed document, for edge lookups. */
|
|
196
|
+
export function reduceHost(state, command, document) {
|
|
197
|
+
switch (command.kind) {
|
|
198
|
+
case 'point':
|
|
199
|
+
return pointed(state, command.key);
|
|
200
|
+
case 'group': {
|
|
201
|
+
// A mark names either an edge (its store identity) or a slot (its lead).
|
|
202
|
+
// A MARK NAMING NEITHER CHANGES NOTHING. The canvas draws an edge the
|
|
203
|
+
// store has not landed yet — a pending create carries a mark from the
|
|
204
|
+
// moment it is proposed — and its identity is in no landed document and
|
|
205
|
+
// is no issue key. Falling through to `pointed` would select that
|
|
206
|
+
// identity as an issue, or worse, commit it as a draft's target.
|
|
207
|
+
if (findEdge(document, command.id) !== undefined)
|
|
208
|
+
return selectEdge(state, command.id);
|
|
209
|
+
if (document.issues.some((issue) => issue.ref === command.id))
|
|
210
|
+
return pointed(state, command.id);
|
|
211
|
+
return settled(state);
|
|
212
|
+
}
|
|
213
|
+
case 'control':
|
|
214
|
+
return controlled(state, command.name, command.target, command.value, document);
|
|
215
|
+
case 'intent':
|
|
216
|
+
return intended(state, command.intent);
|
|
217
|
+
case 'scroll':
|
|
218
|
+
return settled({ ...state, railStart: Math.max(0, Math.floor(command.start)) });
|
|
219
|
+
case 'drag-start':
|
|
220
|
+
return settled({ ...state, drag: command.key });
|
|
221
|
+
case 'drop': {
|
|
222
|
+
const source = state.drag;
|
|
223
|
+
const released = { ...state, drag: null };
|
|
224
|
+
if (source === null || command.key === null || command.key === source)
|
|
225
|
+
return settled(released);
|
|
226
|
+
// A drop is the canvas path's first two facts at once: source, then
|
|
227
|
+
// target. The kind is still to be gathered, at the drop point.
|
|
228
|
+
const begun = createReducer(IDLE_CREATE_DRAFT, { kind: 'begin', source });
|
|
229
|
+
const targeted = createReducer(begun.draft, { kind: 'target', ref: command.key });
|
|
230
|
+
return settled({
|
|
231
|
+
...released,
|
|
232
|
+
draft: targeted.draft,
|
|
233
|
+
drop: command.at,
|
|
234
|
+
selection: selectionReducer(INITIAL_SELECTION, { kind: 'select-issue', key: source }),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Bring the state back into agreement with a document that moved under it.
|
|
241
|
+
*
|
|
242
|
+
* The store re-renders on every landed write, and a write can remove what the
|
|
243
|
+
* state names: a retype or a flip gives the edge a NEW identity, a delete
|
|
244
|
+
* removes it, and a conflict's rehydrate can drop an issue a draft was aimed
|
|
245
|
+
* at. A selection naming an edge the document no longer carries would leave
|
|
246
|
+
* the inspector showing a picker for nothing — the viewer already refuses a
|
|
247
|
+
* stale selection the same way, so the host does too, from the document
|
|
248
|
+
* rather than from memory of what it just proposed.
|
|
249
|
+
*/
|
|
250
|
+
export function reconcileHost(state, document) {
|
|
251
|
+
const edgeId = selectedEdgeId(state.selection);
|
|
252
|
+
const selection = edgeId !== null && findEdge(document, edgeId) === undefined ? INITIAL_SELECTION : state.selection;
|
|
253
|
+
const issueKey = selectedKey(state.selection);
|
|
254
|
+
const known = new Set(document.issues.map((issue) => issue.ref));
|
|
255
|
+
const draftStands = (state.draft.source === null || known.has(state.draft.source)) &&
|
|
256
|
+
(state.draft.target === null || known.has(state.draft.target));
|
|
257
|
+
if (selection === state.selection && draftStands && (issueKey === null || known.has(issueKey))) {
|
|
258
|
+
return state;
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
...state,
|
|
262
|
+
selection: issueKey !== null && !known.has(issueKey) ? INITIAL_SELECTION : selection,
|
|
263
|
+
...(draftStands ? {} : { draft: IDLE_CREATE_DRAFT, targetQuery: '', drop: null }),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/** The issues a target search offers, by reference or title, never the source itself. */
|
|
267
|
+
export function targetMatches(issues, query, source, limit = 8) {
|
|
268
|
+
const needle = query.trim().toLowerCase();
|
|
269
|
+
if (needle === '')
|
|
270
|
+
return [];
|
|
271
|
+
return issues
|
|
272
|
+
.filter((issue) => issue.ref !== source)
|
|
273
|
+
.filter((issue) => issue.ref.includes(needle) || issue.title.toLowerCase().includes(needle))
|
|
274
|
+
.slice(0, limit);
|
|
275
|
+
}
|
|
276
|
+
/** The edge kinds, in the format's order — the keyboard path's `1`–`5` is this list. */
|
|
277
|
+
export const KINDS = EDGE_FIELDS;
|
|
278
|
+
/** How far the reader may scroll into the rail window before it is re-cut around them, in rows. */
|
|
279
|
+
export const RAIL_SLACK = 20;
|
|
280
|
+
/**
|
|
281
|
+
* The slack a window of `count` rows actually gets: `RAIL_SLACK`, bounded to a
|
|
282
|
+
* quarter of the window and never below one row. A slack as wide as the window
|
|
283
|
+
* re-cut a small window onto its own start — ArrowDown on the last drawn row
|
|
284
|
+
* computed `offset - slack` at or below the current start, dispatched it
|
|
285
|
+
* unchanged, and keyboard navigation could not leave the first window.
|
|
286
|
+
*/
|
|
287
|
+
export function railSlackFor(count) {
|
|
288
|
+
return Math.min(RAIL_SLACK, Math.max(1, Math.floor(count / 4)));
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Where the rail window should be re-cut for a scroll position, or `null` when
|
|
292
|
+
* it should stay where it is.
|
|
293
|
+
*
|
|
294
|
+
* `row` is the first visible row (scroll offset over pitch), `start` the
|
|
295
|
+
* window's current first slot, `count` the window's size and `total` the rows
|
|
296
|
+
* in the order. Inside the window's slack band nothing moves. Outside it, the
|
|
297
|
+
* window is re-cut `RAIL_SLACK` rows above the reader, clamped to the order.
|
|
298
|
+
*
|
|
299
|
+
* THE CLAMP CAN LAND ON THE CURRENT START, AND THAT CASE MUST ANSWER `null`.
|
|
300
|
+
* At the end of a long order the window is already pinned to its last start
|
|
301
|
+
* while the reader is deep inside it, so every scroll position there is
|
|
302
|
+
* "outside the band" and clamps back to the same start. A shell that
|
|
303
|
+
* dispatched that as a change redrew, restored the scroll offset — which
|
|
304
|
+
* fires `scroll` again — and never stopped. The decision is a pure function
|
|
305
|
+
* here so that cycle is refused where it can be tested without a browser.
|
|
306
|
+
*/
|
|
307
|
+
export function railWindowTarget(row, start, count, total) {
|
|
308
|
+
const slack = railSlackFor(count);
|
|
309
|
+
const offset = row - start;
|
|
310
|
+
if (offset >= 0 && offset <= count - slack * 2)
|
|
311
|
+
return null;
|
|
312
|
+
const lastStart = Math.max(0, total - count);
|
|
313
|
+
const next = Math.min(lastStart, Math.max(0, Math.floor(row) - slack));
|
|
314
|
+
return next === start ? null : next;
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/workspace/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The workspace's DOM shell — the only module in this package that touches
|
|
3
|
+
* nodes.
|
|
4
|
+
*
|
|
5
|
+
* `renderWorkspace` renders the three-zone workspace as markup and publishes
|
|
6
|
+
* every control as `data-ig-command`; `@issuegraph/viewer` publishes its two
|
|
7
|
+
* identities, `data-ig-key` and `data-ig-group`. A mount reads those, reduces,
|
|
8
|
+
* and renders again — and that loop is this file. What it DECIDES lives in
|
|
9
|
+
* `host.ts`, as a reducer with no DOM, so this file is left with listeners, an
|
|
10
|
+
* `innerHTML` assignment, and the chrome the panels leave to a mount: the add
|
|
11
|
+
* button, the kind chooser, the target search, the delete button.
|
|
12
|
+
*
|
|
13
|
+
* ## Lifted from the demo, in the viewer's shape
|
|
14
|
+
*
|
|
15
|
+
* This was the demo's `workspace.ts`, written once for that page. The viewer
|
|
16
|
+
* made the opposite call for the same problem — it exports `mountViewer` with
|
|
17
|
+
* `update` and `destroy` — and that is the entry point a typed host actually
|
|
18
|
+
* consumes. It took nine review rounds to get this shell right, and every
|
|
19
|
+
* finding was in the shell, none in the reducer; a second host would have
|
|
20
|
+
* re-run them. So the shell ships, in the viewer's shape: one function, one
|
|
21
|
+
* handle, and a container it touches and nothing else.
|
|
22
|
+
*
|
|
23
|
+
* ## `innerHTML`, and why it is not the thing `render.ts` refused
|
|
24
|
+
*
|
|
25
|
+
* Nothing in this file interpolates host text into markup. What IS assigned as
|
|
26
|
+
* markup is the package's own rendered output, which `renderMarkup` escaped —
|
|
27
|
+
* the exact bytes a server-rendered host would send. The chrome beside it is
|
|
28
|
+
* built with `createElement` and `textContent`, so the two disciplines meet at
|
|
29
|
+
* the seam rather than mixing.
|
|
30
|
+
*
|
|
31
|
+
* ## One listener per event, at the root
|
|
32
|
+
*
|
|
33
|
+
* The workspace is re-rendered on every change, so a listener attached to a
|
|
34
|
+
* rendered node dies with it. Delegation at the root is what makes the loop
|
|
35
|
+
* cheap to reason about: one `click`, one `input`, one `keydown`, one scroll
|
|
36
|
+
* (captured, because scroll does not bubble), and the three pointer events the
|
|
37
|
+
* canvas drag needs.
|
|
38
|
+
*
|
|
39
|
+
* ## It reaches no global
|
|
40
|
+
*
|
|
41
|
+
* The document comes from the element the caller passed, which is what keeps
|
|
42
|
+
* this module importable on a runtime that has no DOM — the property
|
|
43
|
+
* `purity.test.ts` measures. An element is recognised by what it can do rather
|
|
44
|
+
* than by `instanceof` against a constructor this module would have to reach
|
|
45
|
+
* for, and a pointer release outside the element is heard on the element's own
|
|
46
|
+
* document rather than on a window.
|
|
47
|
+
*/
|
|
48
|
+
import type { Store, StoreSnapshot } from '@issuegraph/store';
|
|
49
|
+
import { type Theme, type ViewerDocument } from '@issuegraph/viewer';
|
|
50
|
+
import type { AuditInput } from '../audit/findings.ts';
|
|
51
|
+
import type { PickerWords } from '../picker/words.ts';
|
|
52
|
+
import { type HostCommand, type HostState } from './host.ts';
|
|
53
|
+
import { type WorkspaceWords } from './render.ts';
|
|
54
|
+
/** What the canvas zone draws: the editor's scale ladder, or the viewer's tree projection. */
|
|
55
|
+
export declare const CANVAS_MODES: readonly ["neighbourhood", "tree"];
|
|
56
|
+
export type CanvasMode = (typeof CANVAS_MODES)[number];
|
|
57
|
+
/**
|
|
58
|
+
* The words the mount's chrome needs on top of the workspace's own.
|
|
59
|
+
*
|
|
60
|
+
* Required, for the reason `WorkspaceWords` gives: this package does not
|
|
61
|
+
* invent an English sentence, and a default would be one. `picker` is the
|
|
62
|
+
* picker's vocabulary, which the mount draws for a selected edge; `keys` is
|
|
63
|
+
* the one optional entry, because a host may prefer to document the keyboard
|
|
64
|
+
* elsewhere.
|
|
65
|
+
*/
|
|
66
|
+
export interface MountWords extends WorkspaceWords {
|
|
67
|
+
readonly picker: PickerWords;
|
|
68
|
+
/** The control that begins a relationship from the selected issue. */
|
|
69
|
+
readonly addRelationship: string;
|
|
70
|
+
/** The control that proposes deleting the selected edge. */
|
|
71
|
+
readonly deleteRelationship: string;
|
|
72
|
+
/** The control that returns a draft to idle. */
|
|
73
|
+
readonly cancel: string;
|
|
74
|
+
/** The chooser's sentence tail while no target is known yet. */
|
|
75
|
+
readonly chooseKind: string;
|
|
76
|
+
/** The target search's accessible name. */
|
|
77
|
+
readonly targetLabel: string;
|
|
78
|
+
/** The target search's placeholder. */
|
|
79
|
+
readonly targetPlaceholder: string;
|
|
80
|
+
/** A one-line key legend under the inspector, when the host wants one drawn. */
|
|
81
|
+
readonly keys?: string | undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* What the host projects a store snapshot onto.
|
|
85
|
+
*
|
|
86
|
+
* The viewer derives nothing — the order, the holds and the provenance are all
|
|
87
|
+
* inputs — and the audit reads a graph the host built, so both come from the
|
|
88
|
+
* host's projection rather than from anything this mount could compute. An
|
|
89
|
+
* absent `audit` means "not run", which the workspace renders as no header.
|
|
90
|
+
*/
|
|
91
|
+
export interface WorkspaceProjection {
|
|
92
|
+
readonly viewer: ViewerDocument;
|
|
93
|
+
readonly audit?: AuditInput | undefined;
|
|
94
|
+
}
|
|
95
|
+
export interface MountWorkspaceOptions {
|
|
96
|
+
/**
|
|
97
|
+
* The store the host built, with its own `DataSource` and `OrderDeriver`.
|
|
98
|
+
* Fixed for the life of the mount; a host that swaps stores destroys and
|
|
99
|
+
* mounts again. Hydration is the host's: the mount subscribes and redraws on
|
|
100
|
+
* every notification, so a `hydrate()` before or after mounting both land.
|
|
101
|
+
*/
|
|
102
|
+
readonly store: Store;
|
|
103
|
+
/** The host's projection of a snapshot — the landed document is `{ issues, edges: landed }`. */
|
|
104
|
+
readonly project: (snapshot: StoreSnapshot) => WorkspaceProjection;
|
|
105
|
+
readonly words: MountWords;
|
|
106
|
+
readonly theme?: Theme | undefined;
|
|
107
|
+
/** The selector the theme's custom properties are written onto. */
|
|
108
|
+
readonly themeSelector?: string | undefined;
|
|
109
|
+
readonly canvas?: CanvasMode | undefined;
|
|
110
|
+
/** How many rail rows are drawn per window. Wider than the package default so a scroll rarely lands past the drawn rows. */
|
|
111
|
+
readonly railCount?: number | undefined;
|
|
112
|
+
}
|
|
113
|
+
/** What `update` may change. The store is not among them — see {@link MountWorkspaceOptions.store}. */
|
|
114
|
+
export type WorkspaceUpdate = Partial<Omit<MountWorkspaceOptions, 'store'>>;
|
|
115
|
+
export interface WorkspaceHandle {
|
|
116
|
+
/** Take new options, redraw in place, keep the selection and the focus. */
|
|
117
|
+
update(options?: WorkspaceUpdate): void;
|
|
118
|
+
/**
|
|
119
|
+
* Hand the mount a command from the host's own chrome.
|
|
120
|
+
*
|
|
121
|
+
* A host draws controls the mount does not — the demo's writes log, with its
|
|
122
|
+
* retry and discard buttons — outside the mounted element, and this is how
|
|
123
|
+
* those reach the one reducer rather than a second copy of it.
|
|
124
|
+
*/
|
|
125
|
+
dispatch(command: HostCommand): void;
|
|
126
|
+
readonly state: HostState;
|
|
127
|
+
/** Remove every listener this handle added and the nodes it built. */
|
|
128
|
+
destroy(): void;
|
|
129
|
+
}
|
|
130
|
+
/** The package default: wide enough that a scroll rarely lands past the drawn rows. */
|
|
131
|
+
export declare const MOUNT_RAIL_COUNT = 80;
|
|
132
|
+
/**
|
|
133
|
+
* Mount the workspace into an element.
|
|
134
|
+
*
|
|
135
|
+
* Returns a handle rather than nothing, for the viewer's reason: a host that
|
|
136
|
+
* cannot tear this down leaks a listener on every re-render.
|
|
137
|
+
*/
|
|
138
|
+
export declare function mountWorkspace(element: HTMLElement, options: MountWorkspaceOptions): WorkspaceHandle;
|
|
139
|
+
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/workspace/mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAGH,OAAO,KAAK,EAA2B,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,cAAc,EAIpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAOvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,SAAS,EAQf,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,KAAK,cAAc,EAAmB,MAAM,aAAa,CAAC;AAGnE,8FAA8F;AAC9F,eAAO,MAAM,YAAY,oCAAoD,CAAC;AAC9E,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uCAAuC;IACvC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,mBAAmB,CAAC;IACnE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACzC,4HAA4H;IAC5H,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED,uGAAuG;AACvG,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,MAAM,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,sEAAsE;IACtE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,uFAAuF;AACvF,eAAO,MAAM,gBAAgB,KAAK,CAAC;AA0CnC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,qBAAqB,GAAG,eAAe,CAgxBpG"}
|