create-pmos 0.14.0 → 0.16.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 +57 -0
- package/package.json +1 -1
- package/payload/KIT-VERSION +2 -2
- package/workspace/README.md +44 -12
- package/workspace/design-parity.js +358 -0
- package/workspace/lib/console-state.js +48 -1
- package/workspace/lib/engine/workflow-state.js +13 -3
- package/workspace/lib/find-browser.js +60 -0
- package/workspace/lib/focus.js +967 -0
- package/workspace/lib/four-panel.js +345 -0
- package/workspace/lib/git-info.js +28 -1
- package/workspace/lib/handoff.js +280 -0
- package/workspace/lib/layout.js +68 -46
- package/workspace/lib/mobile-nav.js +157 -0
- package/workspace/lib/profiles.js +285 -0
- package/workspace/lib/repo-scan.js +469 -0
- package/workspace/package-lock.json +29 -2
- package/workspace/package.json +14 -4
- package/workspace/public/index.html +79 -279
- package/workspace/public/pm/app.js +242 -0
- package/workspace/public/pm/data.js +877 -0
- package/workspace/public/pm/dom.js +116 -0
- package/workspace/public/pm/fixture.js +979 -0
- package/workspace/public/pm/mobile.css +200 -0
- package/workspace/public/pm/mobile.js +403 -0
- package/workspace/public/pm/modes.js +1076 -0
- package/workspace/public/pm/panel-detail.js +648 -0
- package/workspace/public/pm/panel-initiatives.js +426 -0
- package/workspace/public/pm/panel-repos.js +460 -0
- package/workspace/public/pm/panel-tabs.js +487 -0
- package/workspace/public/pm/state.js +164 -0
- package/workspace/public/pm/tab-doc.js +279 -0
- package/workspace/public/pm/tab-task.js +83 -0
- package/workspace/public/pm/tab-term.js +560 -0
- package/workspace/public/pm/tokens.css +73 -0
- package/workspace/public/vendor/ibm-plex-mono-500.woff2 +0 -0
- package/workspace/server.js +1072 -31
- package/workspace/public/app.js +0 -3450
- package/workspace/public/styles.css +0 -1444
|
@@ -1,298 +1,98 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
|
-
<html lang="en"
|
|
2
|
+
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
|
-
<title>PMOS
|
|
6
|
+
<title>PMOS workspace</title>
|
|
7
7
|
<!-- The terminal's face is preloaded, not left to be discovered. An @font-face is only fetched when
|
|
8
|
-
something first RENDERS in it, which for Plex Mono is about the same moment
|
|
8
|
+
something first RENDERS in it, which for Plex Mono is about the same moment a tab constructs
|
|
9
9
|
the first xterm — and xterm measures its cell from whatever face is resolved at construction.
|
|
10
10
|
Starting the fetch here, during head parse, means the real metrics are in place before the
|
|
11
|
-
first terminal exists.
|
|
11
|
+
first terminal exists. -->
|
|
12
12
|
<link rel="preload" href="/vendor/ibm-plex-mono-400.woff2" as="font" type="font/woff2" crossorigin />
|
|
13
13
|
<link rel="preload" href="/vendor/ibm-plex-mono-700.woff2" as="font" type="font/woff2" crossorigin />
|
|
14
14
|
<link rel="stylesheet" href="/vendor/xterm.css" />
|
|
15
|
-
<link rel="stylesheet" href="/
|
|
15
|
+
<link rel="stylesheet" href="/pm/tokens.css" />
|
|
16
|
+
<!-- The phone surface's stylesheet. It is a separate file from tokens.css on purpose: tokens.css is
|
|
17
|
+
a verbatim copy of the design prototype's token block and is diffed mechanically against it, so
|
|
18
|
+
a media query added there would read as a defect. Everything below the ≤760px breakpoint lives
|
|
19
|
+
here instead, and above the breakpoint this file declares nothing but `display:none`. -->
|
|
20
|
+
<link rel="stylesheet" href="/pm/mobile.css" />
|
|
21
|
+
<!-- xterm and its addons come straight from node_modules through the local server, as globals, so
|
|
22
|
+
the terminal tab can attach a real PTY. No CDN anywhere: this app renders, and works, offline. -->
|
|
23
|
+
<script src="/vendor/xterm.js"></script>
|
|
24
|
+
<script src="/vendor/addon-fit.js"></script>
|
|
25
|
+
<script src="/vendor/addon-web-links.js"></script>
|
|
26
|
+
<!-- ONE table, TWO consumers (W7). The words and glyphs a session is described with — working,
|
|
27
|
+
quiet, needs you, blocked — live in exactly one file, which the SERVER requires and the browser
|
|
28
|
+
loads here. A second copy would be free to drift, and the sidebar and the server would end up
|
|
29
|
+
holding different opinions about one session. Loaded before the module graph so a panel can
|
|
30
|
+
bind from window.PMOSSessionState rather than re-typing a word. -->
|
|
31
|
+
<script src="/lib/session-state.js"></script>
|
|
32
|
+
<!-- The phone's navigation reducer. DOM-free, loaded as a classic script (it is a UMD that sets
|
|
33
|
+
window.PMOSMobileNav) and required by test.js, so the whole screen domain is walkable in node
|
|
34
|
+
rather than only in a browser. pm/mobile.js reads it from the global; the module graph does not
|
|
35
|
+
import it, because a second copy of the reducer is exactly the drift it was extracted to stop. -->
|
|
36
|
+
<script src="/lib/mobile-nav.js"></script>
|
|
37
|
+
<link rel="preload" href="/vendor/ibm-plex-mono-500.woff2" as="font" type="font/woff2" crossorigin />
|
|
16
38
|
</head>
|
|
17
39
|
<body>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<input id="layNewName" type="text" placeholder="e.g. two agents + prd" autocomplete="off" spellcheck="false" maxlength="40" />
|
|
45
|
-
<div class="row"><button type="submit" class="go">create</button>
|
|
46
|
-
<button type="button" class="quiet" id="layNewCancel">cancel</button></div>
|
|
47
|
-
</form>
|
|
48
|
-
<button class="lay-add" id="layNewBtn">+ new layout from this arrangement</button>
|
|
49
|
-
<p class="lay-foot">Layouts belong to <b id="layScope">this repo</b>. Drag a pane by its ⠿ grip,
|
|
50
|
-
or an edge to resize — or use the buttons above. Whatever you change is kept.</p>
|
|
51
|
-
</div>
|
|
40
|
+
<!-- ── the phone surface (≤760px) ────────────────────────────────────────────────────────────────
|
|
41
|
+
Everything else on this page is built by pm/app.js; these two blocks are markup because they
|
|
42
|
+
are the phone's CHROME, and chrome that exists in the document is chrome a screen reader can
|
|
43
|
+
reach in source order — the top bar above the content, the destination nav below it.
|
|
44
|
+
|
|
45
|
+
`hidden` is the SHIPPED state of both. pm/mobile.js removes it only at ≤760px, so above the
|
|
46
|
+
breakpoint this is absent from the accessibility tree rather than merely invisible: a desktop
|
|
47
|
+
PM must not be able to tab into a second navigation system they cannot see. -->
|
|
48
|
+
|
|
49
|
+
<!-- The top bar: back · the screen's name · the ⌘K jump palette · theme. It sits ABOVE .body in
|
|
50
|
+
DOM order because it is the row above the content on screen, and putting it beside the bottom
|
|
51
|
+
nav would read the app backwards. -->
|
|
52
|
+
<div class="mob" id="mobShell" hidden>
|
|
53
|
+
<header class="mob-bar" id="mobBar">
|
|
54
|
+
<button class="mob-back" id="mobBack" type="button" hidden aria-label="Back">‹ back</button>
|
|
55
|
+
<span class="mob-brand" id="mobBrand" aria-hidden="true">◎</span>
|
|
56
|
+
<span class="mob-title" id="mobTitle"></span>
|
|
57
|
+
<!-- The jump palette lives HERE, not in the control bar below. Two reasons, and the second is
|
|
58
|
+
the binding one: it is not a terminal control key (every other button in the bar writes a
|
|
59
|
+
PTY sequence), and that bar is `overflow-x:auto` with seven 44px targets, so at 390px its
|
|
60
|
+
last child sits past the right edge — reachable only by a horizontal scroll nobody would
|
|
61
|
+
guess at. A control the PM cannot see is the hover-only trap in another costume. The
|
|
62
|
+
palette is a jump control for every destination, so it belongs in the bar that is always
|
|
63
|
+
on screen. -->
|
|
64
|
+
<button class="mob-pal" id="mobPalette" type="button" aria-label="Open the jump palette (⌘K)">⌘K</button>
|
|
65
|
+
<button class="mob-theme" id="mobTheme" type="button" aria-label="Toggle theme">◐</button>
|
|
52
66
|
</header>
|
|
67
|
+
</div>
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<span class="grip" id="sideGrip" data-pane="side" role="button" tabindex="0"
|
|
70
|
-
aria-label="Move the sidebar" title="Move this column">⠿</span>
|
|
71
|
-
<!-- R8: the pane states its structure. It was called `work` — the least informative word
|
|
72
|
-
available for a tree of repositories, their working trees, and their sessions. -->
|
|
73
|
-
<button class="fold" id="wsFold" data-fold="ws" aria-expanded="true" title="Hide the repositories, their working trees and their sessions"><span class="chev" aria-hidden="true">▾</span>repos & sessions</button>
|
|
74
|
-
<span class="ct" id="needCount"></span>
|
|
75
|
-
<button class="mini" id="addWsBtn" aria-expanded="false" title="Add a repository">+</button></div>
|
|
76
|
-
<div class="pane-body">
|
|
77
|
-
<button class="newsess" id="newBtn" aria-expanded="false"><i>+</i> new session — run an agent here</button>
|
|
78
|
-
<form class="miniform" id="newForm" hidden>
|
|
79
|
-
<!-- R5: "here" gets a visible referent. The composer has always acted on the selected
|
|
80
|
-
tree; with every repository on screen at once, nothing said which that was. -->
|
|
81
|
-
<p class="where" id="newWhere"></p>
|
|
82
|
-
<label class="lbl" for="newName">name this session</label>
|
|
83
|
-
<input id="newName" type="text" placeholder="e.g. jira-sync build" aria-label="Session name" autocomplete="off" spellcheck="false" />
|
|
84
|
-
<div class="seg" role="radiogroup" aria-label="Agent to run" id="newAgents">
|
|
85
|
-
<button type="button" data-agent="shell" role="radio" aria-checked="true">shell</button>
|
|
86
|
-
<button type="button" data-agent="claude" role="radio" aria-checked="false">claude</button>
|
|
87
|
-
<button type="button" data-agent="codex" role="radio" aria-checked="false">codex</button>
|
|
88
|
-
</div>
|
|
89
|
-
<div class="brwrap" id="newBranchWrap" hidden>
|
|
90
|
-
<label class="lbl" for="newBranch">branch <span class="opt">— optional</span></label>
|
|
91
|
-
<select id="newBranch" aria-label="Branch to run this session on"></select>
|
|
92
|
-
<input id="newBranchName" type="text" hidden placeholder="new-branch-name" aria-label="New branch name" autocomplete="off" spellcheck="false" />
|
|
93
|
-
<label class="chk" id="newIsolateWrap" hidden>
|
|
94
|
-
<input type="checkbox" id="newIsolate" checked />
|
|
95
|
-
<span>give it its own folder — leave running sessions alone</span>
|
|
96
|
-
</label>
|
|
97
|
-
<p class="hint" id="newBranchHint"></p>
|
|
98
|
-
</div>
|
|
99
|
-
<p class="hint" id="newNoGit" hidden>no git in this folder — nothing to branch, the session just starts here</p>
|
|
100
|
-
<div class="row">
|
|
101
|
-
<button type="submit" class="go">start session</button>
|
|
102
|
-
<button type="button" class="quiet" id="newCancel">cancel</button>
|
|
103
|
-
</div>
|
|
104
|
-
</form>
|
|
105
|
-
<div id="tree"></div>
|
|
106
|
-
<div id="workspaces" hidden></div>
|
|
107
|
-
<form class="miniform" id="addWsForm" hidden>
|
|
108
|
-
<button type="button" class="pick" id="pickFolderBtn">📁 Choose folder…</button>
|
|
109
|
-
<label class="lbl" for="addWsPath">or type a path</label>
|
|
110
|
-
<input id="addWsPath" type="text" placeholder="/path/to/another/repo" aria-label="Path to a repository" autocomplete="off" spellcheck="false" />
|
|
111
|
-
<div class="row">
|
|
112
|
-
<button type="submit" class="go">add</button>
|
|
113
|
-
<button type="button" class="quiet" id="addWsCancel">cancel</button>
|
|
114
|
-
</div>
|
|
115
|
-
<p class="hint">or just run <code>pmos</code> inside that repo</p>
|
|
116
|
-
</form>
|
|
117
|
-
<!-- Worktrees the workspace made are folders the PM has to live with, so the app that
|
|
118
|
-
creates them is the app that clears them. Hidden entirely until there is one. -->
|
|
119
|
-
<details class="wtbox" id="wtBox" hidden>
|
|
120
|
-
<summary id="wtSummary">worktrees</summary>
|
|
121
|
-
<div id="wtList"></div>
|
|
122
|
-
</details>
|
|
123
|
-
</div>
|
|
124
|
-
</section>
|
|
125
|
-
|
|
126
|
-
</nav>
|
|
127
|
-
|
|
128
|
-
<main class="term-col" aria-label="Sessions and terminal">
|
|
129
|
-
<!-- Terminal GROUPS (R6). One group is the shipped behaviour; `split` shows a second beside
|
|
130
|
-
it, each with its own tab strip and its own visible session. The #needs strip is NOT
|
|
131
|
-
duplicated — it belongs to the column, not to a group. -->
|
|
132
|
-
<div class="groups" id="groups" data-split="off">
|
|
133
|
-
<section class="group" id="group0" data-g="0">
|
|
134
|
-
<div class="stabs" role="tablist" aria-label="Open sessions" id="stabs"></div>
|
|
135
|
-
<div class="termhost" id="termhost">
|
|
136
|
-
<!-- INSIDE termhost (position:relative): the overlay covers only the terminal area,
|
|
137
|
-
never the sidebar/tabs/needs — those must stay usable while a session is exited. -->
|
|
138
|
-
<div class="exited-overlay" id="exited">
|
|
139
|
-
<div class="card">
|
|
140
|
-
<p id="exitedMsg">This session has exited.</p>
|
|
141
|
-
<div class="row">
|
|
142
|
-
<button id="respawnBtn">↻ respawn</button>
|
|
143
|
-
<button id="removeBtn" class="quiet">✕ remove session</button>
|
|
144
|
-
</div>
|
|
145
|
-
</div>
|
|
146
|
-
</div>
|
|
147
|
-
<div class="empty-overlay" id="noSess">
|
|
148
|
-
<div class="card">
|
|
149
|
-
<p>No sessions in <b id="noSessWs">this workspace</b> yet.</p>
|
|
150
|
-
<p class="reason">+ new session runs an agent here — it starts in this repo's root.</p>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
</section>
|
|
155
|
-
<section class="group" id="group1" data-g="1" hidden>
|
|
156
|
-
<div class="stabs" role="tablist" aria-label="Open sessions, second group" id="stabs1"></div>
|
|
157
|
-
<div class="termhost" id="termhost1">
|
|
158
|
-
<!-- a split with nothing to put in it offers the next step, never an empty black box -->
|
|
159
|
-
<div class="empty-overlay" id="noSess1">
|
|
160
|
-
<div class="card">
|
|
161
|
-
<p>Nothing else to show here yet.</p>
|
|
162
|
-
<p class="reason">Start a second session and it appears in this group.</p>
|
|
163
|
-
<div class="row"><button id="newHere1">+ new session</button>
|
|
164
|
-
<button id="unsplitBtn" class="quiet">✕ close this group</button></div>
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
</section>
|
|
169
|
-
</div>
|
|
170
|
-
<div class="needs" id="needs" role="status" style="display:none"></div>
|
|
171
|
-
|
|
172
|
-
<!-- Scratchpad: a collapsible drawer at the BOTTOM of the terminal column. Folded it is a thin
|
|
173
|
-
bar; open it takes a bounded slice below the terminal — it never overlays the tabs, the
|
|
174
|
-
terminal, or the document rail. Persists PER TAB: each session keeps its own staging
|
|
175
|
-
text, and the label below says which tab you are staging for. -->
|
|
176
|
-
<section class="scratch" id="scratch" data-open="false" aria-label="Scratchpad">
|
|
177
|
-
<div class="scratch-head">
|
|
178
|
-
<button type="button" class="scratch-toggle" id="scratchToggle" aria-expanded="false" aria-controls="scratchText">
|
|
179
|
-
<span class="chev" aria-hidden="true">▴</span> scratchpad
|
|
180
|
-
</button>
|
|
181
|
-
<span class="scratch-who" id="scratchWho"></span>
|
|
182
|
-
<span class="scratch-status" id="scratchStatus" role="status"></span>
|
|
183
|
-
<span class="scratch-actions">
|
|
184
|
-
<button type="button" class="mini" id="scratchCopy" title="Copy to clipboard">copy</button>
|
|
185
|
-
<button type="button" class="mini" id="scratchSend" title="Paste into the active terminal (does not press enter)">→ terminal</button>
|
|
186
|
-
</span>
|
|
187
|
-
</div>
|
|
188
|
-
<textarea id="scratchText" class="scratch-text" placeholder="Stage commands or notes here, then copy or send them to the terminal…" spellcheck="false" autocomplete="off" aria-label="Scratchpad text"></textarea>
|
|
189
|
-
</section>
|
|
190
|
-
</main>
|
|
191
|
-
|
|
192
|
-
<aside class="rail" id="rail" aria-label="Library and document">
|
|
193
|
-
<div class="railgrip edge" id="railGrip" data-edge="read" role="separator" aria-label="Resize the reader" tabindex="0"></div>
|
|
194
|
-
<section class="pane lib-pane" id="paneLib">
|
|
195
|
-
<div class="cap">
|
|
196
|
-
<span class="grip" id="readGrip" data-pane="reader" role="button" tabindex="0"
|
|
197
|
-
aria-label="Move the reader" title="Move this pane">⠿</span>
|
|
198
|
-
<button class="fold" id="libFold" aria-expanded="true" title="Hide the library"><span class="chev" aria-hidden="true">▾</span>library</button>
|
|
199
|
-
<!-- R7 — the four standing lenses are gone. What the rail shows follows the SELECTION:
|
|
200
|
-
a repository group gives repo detail (the folder map, its schedules, its history), a
|
|
201
|
-
tree row gives that initiative's dossier. The views below are the sub-views of
|
|
202
|
-
whichever of those two is current, rendered by renderLensTabs(). -->
|
|
203
|
-
<span class="lens" role="tablist" aria-label="Detail view" id="lensTabs"></span>
|
|
204
|
-
<span class="reading" id="libWho" title="the repository these documents come from"></span>
|
|
205
|
-
<button class="mini librefresh" id="libRefresh" title="Rescan the repository for new files & folders" aria-label="Refresh the library">↻</button>
|
|
206
|
-
</div>
|
|
207
|
-
<div class="pane-body">
|
|
208
|
-
<input class="libfind" id="libFind" type="search" placeholder="filter the library…" aria-label="Filter the library" autocomplete="off" />
|
|
209
|
-
<div id="library"></div>
|
|
210
|
-
</div>
|
|
211
|
-
</section>
|
|
212
|
-
|
|
213
|
-
<div class="railsplit" id="railSplit" role="separator" aria-label="Resize the library and document panes" tabindex="0" hidden></div>
|
|
214
|
-
|
|
215
|
-
<section class="pane doc-pane" id="paneDoc" hidden>
|
|
216
|
-
<div class="cap">
|
|
217
|
-
<button class="fold" id="docFold" aria-expanded="true" title="Hide the document"><span class="chev" aria-hidden="true">▾</span>document</button>
|
|
218
|
-
<span class="crumb" id="crumb"></span>
|
|
219
|
-
<button class="mini docrev" id="docEdit" hidden title="Edit this document">edit</button>
|
|
220
|
-
<button class="mini docrev" id="docSave" hidden title="Save (⌘S)">save</button>
|
|
221
|
-
<button class="mini docrev" id="docCancel" hidden title="Discard changes">cancel</button>
|
|
222
|
-
<button class="mini docrev" id="docHistory" hidden title="Changes you have made to this document">history</button>
|
|
223
|
-
<button class="x" id="closeDoc" aria-label="Close document">✕</button>
|
|
224
|
-
</div>
|
|
225
|
-
<div class="pane-body doc-body" id="docBody" tabindex="0"></div>
|
|
226
|
-
</section>
|
|
227
|
-
</aside>
|
|
228
|
-
|
|
229
|
-
<!-- Drop targets, shown only while a ⠿ grip is being dragged. They are an ACCELERATOR: every
|
|
230
|
-
position they offer is also reachable from the layout menu, so the drag is never the only
|
|
231
|
-
path to an arrangement (R12). -->
|
|
232
|
-
<div class="drop" id="drop" aria-hidden="true">
|
|
233
|
-
<div class="dz" data-z="left">left</div>
|
|
234
|
-
<div class="dz" data-z="right">right</div>
|
|
235
|
-
<div class="dz" data-z="bottom">bottom</div>
|
|
236
|
-
<div class="dz" data-z="off">hide</div>
|
|
237
|
-
</div>
|
|
238
|
-
</div>
|
|
239
|
-
|
|
240
|
-
<!-- ⌘K jump palette (client-side; no backend) -->
|
|
241
|
-
<div class="palette" id="palette" role="dialog" aria-modal="true" aria-label="Jump" style="display:none">
|
|
242
|
-
<div class="palette-box">
|
|
243
|
-
<input id="palInput" type="text" placeholder="Summon a view (initiatives, roadmap, okr, report) or jump to a session, initiative, document…" aria-label="Summon a view or jump to a workspace, session, initiative or document" autocomplete="off" />
|
|
244
|
-
<div class="palette-list" id="palList" role="listbox"></div>
|
|
245
|
-
</div>
|
|
246
|
-
</div>
|
|
247
|
-
|
|
248
|
-
<!-- in-app folder browser — the stand-in when the machine has no native chooser -->
|
|
249
|
-
<div class="palette" id="fsPicker" role="dialog" aria-modal="true" aria-label="Choose a repository" style="display:none">
|
|
250
|
-
<div class="palette-box">
|
|
251
|
-
<div class="fs-head">
|
|
252
|
-
<button class="fs-up" id="fsUp" aria-label="Parent folder">↑</button>
|
|
253
|
-
<span class="fs-crumb" id="fsCrumb"></span>
|
|
254
|
-
<button class="fs-use" id="fsUse">use this folder</button>
|
|
255
|
-
<button class="x" id="fsClose" aria-label="Cancel">✕</button>
|
|
256
|
-
</div>
|
|
257
|
-
<div class="palette-list" id="fsList" role="listbox"></div>
|
|
258
|
-
</div>
|
|
259
|
-
</div>
|
|
260
|
-
|
|
261
|
-
<!-- Mobile only (≤760px): a terminal control-key accessory bar (phones lack these keys) over a
|
|
262
|
-
pane switcher. Hidden on desktop via CSS; the switcher swaps the single visible column. -->
|
|
263
|
-
<div class="mobmenu" id="mobMenu" data-view="terminal">
|
|
264
|
-
<div class="ctrlbar" id="ctrlBar" role="toolbar" aria-label="Terminal control keys">
|
|
265
|
-
<button type="button" data-seq="esc" aria-label="Escape"><span class="lbl">esc</span></button>
|
|
266
|
-
<button type="button" data-seq="tab" aria-label="Tab"><span class="lbl">tab</span></button>
|
|
267
|
-
<button type="button" id="ctrlKey" aria-pressed="false" aria-label="Control modifier (one-shot)"><span class="lbl">ctrl</span></button>
|
|
268
|
-
<button type="button" data-seq="left" aria-label="Left arrow">←</button>
|
|
269
|
-
<button type="button" data-seq="up" aria-label="Up arrow">↑</button>
|
|
270
|
-
<button type="button" data-seq="down" aria-label="Down arrow">↓</button>
|
|
271
|
-
<button type="button" data-seq="right" aria-label="Right arrow">→</button>
|
|
272
|
-
<button type="button" id="mobPalette" aria-label="Open the jump palette (⌘K)">⌘K</button>
|
|
273
|
-
</div>
|
|
274
|
-
<nav class="mobtabs" role="tablist" aria-label="Switch pane">
|
|
275
|
-
<button type="button" role="tab" data-mview="sessions" aria-selected="false">sessions</button>
|
|
276
|
-
<button type="button" role="tab" data-mview="terminal" aria-selected="true">terminal</button>
|
|
277
|
-
<button type="button" role="tab" data-mview="library" aria-selected="false">library</button>
|
|
278
|
-
</nav>
|
|
69
|
+
<!-- The bottom block: a terminal control-key accessory bar (terminal screen only — phones have no
|
|
70
|
+
Esc/Tab/Ctrl/arrows) over the five-destination nav. The nav is a <nav> of buttons carrying
|
|
71
|
+
aria-current, NOT a tablist: the retired markup declared role="tablist" over role="tab"
|
|
72
|
+
children with no tabpanel and no aria-controls anywhere, which is a promise the DOM did not
|
|
73
|
+
keep. Selecting a destination resets it to its root; depth is pushed on top of it and #mobBack
|
|
74
|
+
pops one screen. The glyphs are the mobile prototype's own (◧ ◔ ◐ ◒ ☰). -->
|
|
75
|
+
<div class="mobmenu" id="mobMenu" hidden>
|
|
76
|
+
<div class="ctrlbar" id="ctrlBar" role="toolbar" aria-label="Terminal control keys">
|
|
77
|
+
<button type="button" data-seq="esc" aria-label="Escape"><span class="lbl">esc</span></button>
|
|
78
|
+
<button type="button" data-seq="tab" aria-label="Tab"><span class="lbl">tab</span></button>
|
|
79
|
+
<button type="button" id="ctrlKey" aria-pressed="false" aria-label="Control modifier (one-shot)"><span class="lbl">ctrl</span></button>
|
|
80
|
+
<button type="button" data-seq="left" aria-label="Left arrow">←</button>
|
|
81
|
+
<button type="button" data-seq="up" aria-label="Up arrow">↑</button>
|
|
82
|
+
<button type="button" data-seq="down" aria-label="Down arrow">↓</button>
|
|
83
|
+
<button type="button" data-seq="right" aria-label="Right arrow">→</button>
|
|
279
84
|
</div>
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
<span
|
|
283
|
-
<
|
|
284
|
-
|
|
85
|
+
<nav class="mobnav" id="mobNav" aria-label="Sections">
|
|
86
|
+
<button type="button" class="mobnav-b" data-dest="board" aria-current="page"><span class="g" aria-hidden="true">◧</span><span class="l">board</span></button>
|
|
87
|
+
<button type="button" class="mobnav-b" data-dest="scheduled" aria-current="false"><span class="g" aria-hidden="true">◔</span><span class="l">scheduled</span></button>
|
|
88
|
+
<button type="button" class="mobnav-b" data-dest="agents" aria-current="false"><span class="g" aria-hidden="true">◐</span><span class="l">agents</span></button>
|
|
89
|
+
<button type="button" class="mobnav-b" data-dest="memory" aria-current="false"><span class="g" aria-hidden="true">◒</span><span class="l">memory</span></button>
|
|
90
|
+
<button type="button" class="mobnav-b" data-dest="more" aria-current="false"><span class="g" aria-hidden="true">☰</span><span class="l">more</span></button>
|
|
91
|
+
</nav>
|
|
285
92
|
</div>
|
|
286
93
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
<script src="/
|
|
290
|
-
<script src="/lib/preview-kind.js"></script>
|
|
291
|
-
<script src="/lib/layout.js"></script>
|
|
292
|
-
<script src="/lib/session-state.js"></script>
|
|
293
|
-
<!-- The editor computes its diff with the SAME module the server saves through, so what you see
|
|
294
|
-
while editing and what the server writes can never disagree. -->
|
|
295
|
-
<script src="/lib/apply-change.js"></script>
|
|
296
|
-
<script src="/app.js"></script>
|
|
94
|
+
<!-- The rest of the surface is built by pm/app.js: the root element carries data-pm-theme and is
|
|
95
|
+
appended here at boot. Nothing is server-rendered, so there is no markup here to keep in sync. -->
|
|
96
|
+
<script type="module" src="/pm/app.js"></script>
|
|
297
97
|
</body>
|
|
298
98
|
</html>
|