@bongos/core 1.21.26 → 1.21.27
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/.bongos-core.json +53 -53
- package/docs/copy-inventory.md +8 -8
- package/docs/copy-registry.json +9 -9
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-readings.json +87 -87
- package/modules/hall-ui/public/atlas.html +1 -1
- package/modules/hall-ui/public/blockers.html +1 -1
- package/modules/hall-ui/public/board-room.html +1 -1
- package/modules/hall-ui/public/city.html +1 -1
- package/modules/hall-ui/public/collab.html +1 -1
- package/modules/hall-ui/public/commands.html +1 -1
- package/modules/hall-ui/public/copy-desk.html +1 -1
- package/modules/hall-ui/public/deploy.html +1 -1
- package/modules/hall-ui/public/diagrams.html +1 -1
- package/modules/hall-ui/public/drachmae.html +1 -1
- package/modules/hall-ui/public/fleet.html +1 -1
- package/modules/hall-ui/public/gate.html +1 -1
- package/modules/hall-ui/public/goal-map.html +1 -1
- package/modules/hall-ui/public/goals.html +1 -1
- package/modules/hall-ui/public/government.html +1 -1
- package/modules/hall-ui/public/idea.html +1 -1
- package/modules/hall-ui/public/ideas.html +1 -1
- package/modules/hall-ui/public/index.html +1 -1
- package/modules/hall-ui/public/modules.html +1 -1
- package/modules/hall-ui/public/primer.html +1 -1
- package/modules/hall-ui/public/profile.html +1 -1
- package/modules/hall-ui/public/project-settings.html +1 -1
- package/modules/hall-ui/public/ranks.html +1 -1
- package/modules/hall-ui/public/roadmap.html +1 -1
- package/modules/hall-ui/public/roster.html +1 -1
- package/modules/hall-ui/public/sessions.html +1 -1
- package/modules/hall-ui/public/settings.html +1 -1
- package/modules/hall-ui/public/shell.js +97 -60
- package/modules/hall-ui/public/street.html +1 -1
- package/modules/hall-ui/public/studio.html +1 -1
- package/modules/hall-ui/public/style.css +46 -0
- package/modules/hall-ui/public/task.html +1 -1
- package/modules/hall-ui/public/thinking.html +1 -1
- package/modules/hall-ui/public/tweak-editor.html +1 -1
- package/modules/hall-ui/public/watch.html +1 -1
- package/modules/hall-ui/public/work.html +1 -1
- package/modules/hall-ui/records/hall-navigation.md +7 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +6 -0
- package/src/module-api.js +1 -1
- package/tests/hall_fullscreen.mjs +122 -5
- package/tests/hall_tweak_editor.mjs +1 -1
- package/tests/nav_permission_atoms.mjs +1 -1
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
|
|
92
92
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
93
93
|
|
|
94
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
94
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
95
95
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
96
96
|
<script src="/builders/palette.js" defer></script>
|
|
97
97
|
<script src="/builders/atlas.js?v=2026-09-02-index" defer></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
52
52
|
chrome exists before the page script runs. -->
|
|
53
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
54
54
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
55
55
|
<script src="/builders/palette.js" defer></script>
|
|
56
56
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
62
62
|
|
|
63
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
63
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
64
64
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
65
65
|
<script src="/builders/palette.js" defer></script>
|
|
66
66
|
<script src="/builders/dom-utils.js?v=2026-06-16-board"></script>
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
85
85
|
|
|
86
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
86
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
87
87
|
<script src="/builders/palette.js" defer></script>
|
|
88
88
|
<script src="/builders/city-draw.js?v=2026-10-02-city1"></script>
|
|
89
89
|
<script src="/builders/city.js?v=2026-10-02-city1"></script>
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
|
|
149
149
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
150
150
|
|
|
151
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
151
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
152
152
|
<script src="/builders/palette.js" defer></script>
|
|
153
153
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
154
154
|
<script src="/builders/collab-lib.js?v=2026-09-24-archive"></script>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
56
|
|
|
57
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
57
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
58
58
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
59
59
|
<script src="/builders/palette.js" defer></script>
|
|
60
60
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
|
|
178
178
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
179
179
|
|
|
180
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
180
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
181
181
|
<script src="/builders/palette.js" defer></script>
|
|
182
182
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
183
183
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
|
|
75
75
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
76
76
|
|
|
77
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
77
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
78
78
|
<script src="/builders/palette.js" defer></script>
|
|
79
79
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
80
80
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
99
99
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
100
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
100
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
101
101
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
102
102
|
<script src="/builders/palette.js" defer></script>
|
|
103
103
|
<script src="/builders/diagram-viewer.js?v=2026-06-14-diagviewer-1" defer></script>
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
|
|
99
99
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
100
100
|
|
|
101
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
101
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
102
102
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
103
103
|
<script src="/builders/palette.js" defer></script>
|
|
104
104
|
<script src="/builders/md-reader.js?v=2026-09-02-mdreader-2"></script>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
56
56
|
|
|
57
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
57
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
58
58
|
<script src="/builders/palette.js" defer></script>
|
|
59
59
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
60
60
|
<script src="/builders/hall-kit.js"></script>
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
<div id="gate-modal-root"></div>
|
|
78
78
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
79
79
|
|
|
80
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
80
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
81
81
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
82
82
|
<script src="/builders/palette.js" defer></script>
|
|
83
83
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
</div>
|
|
138
138
|
</div>
|
|
139
139
|
|
|
140
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
140
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
141
141
|
<script src="/builders/palette.js" defer></script>
|
|
142
142
|
|
|
143
143
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
|
|
231
231
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
232
232
|
|
|
233
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
233
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
234
234
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
235
235
|
<script src="/builders/palette.js" defer></script>
|
|
236
236
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
|
|
135
135
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
136
136
|
|
|
137
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
137
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
138
138
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
139
139
|
<script src="/builders/palette.js" defer></script>
|
|
140
140
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
|
|
51
51
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
52
52
|
|
|
53
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
53
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
54
54
|
<script src="/builders/palette.js" defer></script>
|
|
55
55
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib" defer></script>
|
|
56
56
|
<!-- task-detail.js still owns the #/idea/N and #/blocker/N overlay, so a ref
|
|
@@ -225,7 +225,7 @@
|
|
|
225
225
|
|
|
226
226
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
227
227
|
|
|
228
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
228
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
229
229
|
<script src="/builders/palette.js" defer></script>
|
|
230
230
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
231
231
|
<!-- task 1003069 (R08) — the quick-filing form's routed result links a task
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
<script src="/builders/brand-apply.js?v=2026-06-27-r75" defer></script>
|
|
107
107
|
<!-- The app shell (sidebar + top bar + view router). Dependency-free; loaded
|
|
108
108
|
BEFORE builders.js so the chrome ids exist when events are wired. -->
|
|
109
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
109
|
+
<script src="/builders/shell.js?v=2026-10-02-trail" defer></script>
|
|
110
110
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
111
111
|
<script src="/builders/palette.js" defer></script>
|
|
112
112
|
<!-- task 2166: the shared component kit (window.OTBKit) — pager/ledger/rail.
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
|
|
102
102
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
103
103
|
|
|
104
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
104
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
105
105
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
106
106
|
<script src="/builders/palette.js" defer></script>
|
|
107
107
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
|
|
116
116
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
117
117
|
|
|
118
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
118
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
119
119
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
120
120
|
<script src="/builders/palette.js" defer></script>
|
|
121
121
|
<!-- the shared markdown reader (window.OTBMdReader) — primer.js renders through
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
|
|
207
207
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
208
208
|
chrome exists before the page script runs. -->
|
|
209
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
209
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
210
210
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
211
211
|
<script src="/builders/palette.js" defer></script>
|
|
212
212
|
<!-- shared frontend toolkit (window.OTB) — loaded before profile.js, which pulls from it. -->
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
60
60
|
|
|
61
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
61
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
62
62
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
63
63
|
<script src="/builders/palette.js" defer></script>
|
|
64
64
|
<script src="/builders/dom-utils.js?v=2026-06-16-gate"></script>
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
|
|
78
78
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
79
79
|
chrome exists before the page script runs. -->
|
|
80
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
80
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
81
81
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
82
82
|
<script src="/builders/palette.js" defer></script>
|
|
83
83
|
<!-- shared frontend toolkit (window.OTB) — loaded before ranks.js, which pulls from it. -->
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
43
43
|
|
|
44
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
44
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
45
45
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
46
46
|
<script src="/builders/palette.js" defer></script>
|
|
47
47
|
<script src="/builders/dom-utils.js?v=2026-06-14-domutils"></script>
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
|
|
54
54
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
55
55
|
chrome exists before the page script runs. -->
|
|
56
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
56
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
57
57
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
58
58
|
<script src="/builders/palette.js" defer></script>
|
|
59
59
|
<!-- shared frontend toolkit (window.OTB — rank labels, number formats) + the
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
|
|
112
112
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
113
113
|
chrome exists before the page script runs. -->
|
|
114
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
114
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
115
115
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
116
116
|
<script src="/builders/palette.js" defer></script>
|
|
117
117
|
<!-- shared frontend toolkit (window.OTB) — loaded BEFORE sessions.js so it can pull from it. -->
|
|
@@ -435,7 +435,7 @@
|
|
|
435
435
|
|
|
436
436
|
<!-- The app shell (sidebar + top bar). Dependency-free; loaded FIRST so the
|
|
437
437
|
chrome exists before the page scripts run. -->
|
|
438
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
438
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
439
439
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
440
440
|
<script src="/builders/palette.js" defer></script>
|
|
441
441
|
<!-- shared frontend toolkit (window.OTB) — loaded before consuming IIFEs. -->
|
|
@@ -507,35 +507,16 @@
|
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
// ---------- the Back link (task 1004430) ----------
|
|
510
|
-
// A page reached
|
|
511
|
-
//
|
|
512
|
-
//
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
// same-origin referrer.
|
|
517
|
-
//
|
|
518
|
-
// task 1004477: this is the ONLY place a hall page's way back is decided —
|
|
519
|
-
// no page draws its own Back link any more. Two hooks cover what the page
|
|
520
|
-
// copies used to:
|
|
521
|
-
// - <body data-back-fallback="/work"> names where Back goes when there is
|
|
522
|
-
// no origin at all (a deep-linked task or idea, the tweak editor);
|
|
523
|
-
// - a link marked [data-shell-exit] is a second exit the page places (an
|
|
524
|
-
// error state's button, the tweak editor's bar in full screen, where the
|
|
525
|
-
// top bar is hidden), and the shell fills its address and its words.
|
|
510
|
+
// A page reached from INSIDE another hall page (`?from=`, else a same-origin
|
|
511
|
+
// referrer) shows "← <that page>" in the top bar. A sidebar hop is not a
|
|
512
|
+
// drill-down: its click leaves a one-shot sessionStorage note, and the page it
|
|
513
|
+
// lands on shows none. task 1004477: the ONLY place a page's way back is
|
|
514
|
+
// decided. <body data-back-fallback="/work"> names where Back goes with no
|
|
515
|
+
// origin; a [data-shell-exit] link the page places is filled by the shell.
|
|
526
516
|
var NAV_HOP_KEY = 'hall-nav-hop';
|
|
527
517
|
function hallPath(url) {
|
|
528
518
|
return String(url.pathname).replace(/^\/builders(?=\/|$)/, '').replace(/\.html$/, '').replace(/\/index$/, '') || '/';
|
|
529
519
|
}
|
|
530
|
-
function backOrigin() {
|
|
531
|
-
var hop = null;
|
|
532
|
-
try {
|
|
533
|
-
hop = window.sessionStorage.getItem(NAV_HOP_KEY);
|
|
534
|
-
window.sessionStorage.removeItem(NAV_HOP_KEY);
|
|
535
|
-
} catch (_) { /* private mode: no note, so fall through */ }
|
|
536
|
-
if (hop && hop === hallPath(location)) return null;
|
|
537
|
-
return linkOrigin() || fallbackOrigin();
|
|
538
|
-
}
|
|
539
520
|
// The page this one was opened from: ?from=, then a same-origin referrer.
|
|
540
521
|
function linkOrigin() {
|
|
541
522
|
var from = null;
|
|
@@ -548,21 +529,18 @@
|
|
|
548
529
|
if (!from || from.origin !== location.origin) return null;
|
|
549
530
|
var path = hallPath(from);
|
|
550
531
|
if (/^\/(api|auth|lib)(\/|$)/.test(path)) return null;
|
|
551
|
-
//
|
|
552
|
-
//
|
|
532
|
+
// Keep the origin's query (a filtered list) but never its own ?from=, which
|
|
533
|
+
// would chain; and compare without OUR ?from=, so a self-link is refused.
|
|
553
534
|
var params = new URLSearchParams(from.search);
|
|
554
535
|
params.delete('from');
|
|
555
536
|
var search = params.toString() ? '?' + params.toString() : '';
|
|
556
|
-
// This page's address without its own ?from=, so `?from=` naming the page
|
|
557
|
-
// itself (a loop, not a way back) is caught like any other self-link.
|
|
558
537
|
var ownParams = new URLSearchParams(location.search || '');
|
|
559
538
|
ownParams.delete('from');
|
|
560
539
|
var here = hallPath(location) + (ownParams.toString() ? '?' + ownParams.toString() : '');
|
|
561
540
|
if (path + search === here) return null;
|
|
562
541
|
return { href: path + search + (from.hash || ''), path: path, label: backLabel(path, from.hash), viaReferrer: viaReferrer };
|
|
563
542
|
}
|
|
564
|
-
//
|
|
565
|
-
// honoured only as a path on this host (one leading slash, never the API).
|
|
543
|
+
// <body data-back-fallback>, honoured only as a path on this host (never the API).
|
|
566
544
|
function fallbackOrigin() {
|
|
567
545
|
var f = document.body && document.body.dataset && document.body.dataset.backFallback;
|
|
568
546
|
if (!f || !/^\/(?!\/)/.test(f) || /[\\\s]/.test(f)) return null;
|
|
@@ -573,14 +551,12 @@
|
|
|
573
551
|
if (/^\/(api|auth|lib)(\/|$)/.test(path) || path === hallPath(location)) return null;
|
|
574
552
|
return { href: path + (u.search || '') + (u.hash || ''), path: path, label: backLabel(path, u.hash), viaReferrer: false };
|
|
575
553
|
}
|
|
576
|
-
// "Back to tasks"
|
|
577
|
-
// so it is lowercased unless it carries an acronym ("API docs").
|
|
554
|
+
// "Back to tasks": a nav label is lowercased mid-sentence unless it has an acronym.
|
|
578
555
|
function exitWords(label) {
|
|
579
556
|
return 'Back to ' + (/[A-Z]{2}/.test(label) ? label : label.toLowerCase());
|
|
580
557
|
}
|
|
581
|
-
// Fill every [data-shell-exit]
|
|
582
|
-
//
|
|
583
|
-
// renders an exit later (task.js's failure states) calls this once it has.
|
|
558
|
+
// Fill every [data-shell-exit] under `root` with the way back (else home); a
|
|
559
|
+
// page that renders one later (task.js's failure states) calls this again.
|
|
584
560
|
function fillExits(root) {
|
|
585
561
|
var scope = root || document;
|
|
586
562
|
if (!scope.querySelectorAll) return;
|
|
@@ -610,39 +586,99 @@
|
|
|
610
586
|
}
|
|
611
587
|
return 'Back';
|
|
612
588
|
}
|
|
613
|
-
|
|
589
|
+
// ---------- the trail (task 1004476) ----------
|
|
590
|
+
// Two clicks deep the bar shows the run of pages that led here, "Goals › goal
|
|
591
|
+
// 12 › task 340", the last crumb being Back. Kept per tab (sessionStorage) as
|
|
592
|
+
// crumbs ending with THIS page: a drill-down cuts after its origin and appends;
|
|
593
|
+
// returning to a crumb (the origin, if any, sits after it) trims; an unknown
|
|
594
|
+
// origin starts fresh by the ?from= / referrer / fallback rules; a sidebar hop
|
|
595
|
+
// starts over. Storage that throws, or no URL API, keeps the one-step Back.
|
|
596
|
+
var TRAIL_KEY = 'hall-nav-trail', TRAIL_MAX = 4, BACK = null;
|
|
597
|
+
function hereCrumb() {
|
|
598
|
+
var own = new URLSearchParams(location.search || ''); own.delete('from');
|
|
599
|
+
var path = hallPath(location), hash = location.hash || '';
|
|
600
|
+
return { href: path + (own.toString() ? '?' + own.toString() : '') + hash, label: backLabel(path, hash) };
|
|
601
|
+
}
|
|
602
|
+
// A stored crumb is honoured only as a path on this host with a string label.
|
|
603
|
+
function crumbOk(c) {
|
|
604
|
+
return !!c && typeof c.href === 'string' && typeof c.label === 'string' &&
|
|
605
|
+
/^\/(?!\/)/.test(c.href) && !/[\\\s]/.test(c.href) && !/^\/(api|auth|lib)(\/|[?#]|$)/.test(c.href);
|
|
606
|
+
}
|
|
607
|
+
function readTrail() {
|
|
608
|
+
try { var t = JSON.parse(window.sessionStorage.getItem(TRAIL_KEY) || '[]'); return Array.isArray(t) ? t.filter(crumbOk) : []; } catch (_) { return null; }
|
|
609
|
+
}
|
|
610
|
+
function writeTrail(t) {
|
|
611
|
+
try { window.sessionStorage.setItem(TRAIL_KEY, JSON.stringify(t.slice(-(TRAIL_MAX + 1)))); } catch (_) { /* private mode */ }
|
|
612
|
+
}
|
|
613
|
+
// Latest crumb at `href`; a referrer has no #hash, so it matches on the address alone.
|
|
614
|
+
function crumbAt(t, href, anyHash) {
|
|
615
|
+
for (var i = t.length - 1; i >= 0; i--) if (anyHash ? t[i].href.split('#')[0] === href.split('#')[0] : t[i].href === href) return i;
|
|
616
|
+
return -1;
|
|
617
|
+
}
|
|
618
|
+
// The crumbs before this page; the last is where Back goes. Sets BACK.
|
|
619
|
+
function trailCrumbs() {
|
|
620
|
+
var hop = null, here = null;
|
|
621
|
+
try { hop = window.sessionStorage.getItem(NAV_HOP_KEY); window.sessionStorage.removeItem(NAV_HOP_KEY); } catch (_) { /* private mode */ }
|
|
622
|
+
try { here = hereCrumb(); } catch (_) { /* no URL API */ }
|
|
623
|
+
var stored = here ? readTrail() : null, t = stored || [], trail = null, via = false;
|
|
624
|
+
here = here || { href: '', label: '' };
|
|
625
|
+
if (hop && hop === hallPath(location)) trail = [here];
|
|
626
|
+
var origin = trail ? null : linkOrigin();
|
|
627
|
+
var at = crumbAt(t, here.href), from = origin ? crumbAt(t, origin.href, origin.viaReferrer) : -1;
|
|
628
|
+
var f = trail || origin || at >= 0 ? null : fallbackOrigin();
|
|
629
|
+
if (!trail && at >= 0 && (!origin || from > at)) trail = t.slice(0, at + 1);
|
|
630
|
+
else if (!trail && origin) { trail = (from >= 0 ? t.slice(0, from + 1) : [origin]).concat([here]); via = origin.viaReferrer; }
|
|
631
|
+
else if (!trail) trail = f ? [f, here] : [here];
|
|
632
|
+
trail = trail.slice(-(TRAIL_MAX + 1)).map(function (c) { return { href: c.href, label: c.label }; });
|
|
633
|
+
if (stored) writeTrail(trail);
|
|
634
|
+
var crumbs = trail.slice(0, -1), last = crumbs[crumbs.length - 1];
|
|
635
|
+
BACK = last ? { href: last.href, label: last.label, viaReferrer: via } : null;
|
|
636
|
+
return crumbs;
|
|
637
|
+
}
|
|
638
|
+
// A hash route moves without a page load: a record view is a drill-down, a
|
|
639
|
+
// crumb already held is a return, any other view just renames this page's crumb.
|
|
640
|
+
function onTrailHash() {
|
|
641
|
+
var t = readTrail(), here;
|
|
642
|
+
if (!t || !t.length || t[t.length - 1].href.split(/[?#]/)[0] !== hallPath(location)) return;
|
|
643
|
+
try { here = hereCrumb(); } catch (_) { return; }
|
|
644
|
+
var at = crumbAt(t, here.href);
|
|
645
|
+
if (at >= 0) t = t.slice(0, at + 1);
|
|
646
|
+
else if (/^#\/(task|idea|blocker|goal)\/\d+/.test(location.hash || '')) t = t.concat([here]);
|
|
647
|
+
else t[t.length - 1] = here;
|
|
648
|
+
writeTrail(t);
|
|
649
|
+
}
|
|
650
|
+
var BACK_ICON = '<svg viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M11 4 6 9l5 5"/></svg>';
|
|
651
|
+
// Narrower windows fold the trail (style.css): the middle goes to "…", then
|
|
652
|
+
// the first crumb joins it and "…" links to the start, then only Back is left.
|
|
614
653
|
function backLinkHtml() {
|
|
615
|
-
|
|
654
|
+
var crumbs = trailCrumbs(), sep = '<span class="topbar-trail__sep" aria-hidden="true">›</span>';
|
|
616
655
|
if (!BACK) return '';
|
|
617
|
-
|
|
618
|
-
'<
|
|
619
|
-
|
|
656
|
+
var back = '<a class="topbar-back" id="topbar-back" href="' + esc(BACK.href) + '" title="Back to ' + esc(BACK.label) + '">' +
|
|
657
|
+
BACK_ICON + '<span class="topbar-back__label">' + esc(BACK.label) + '</span></a>';
|
|
658
|
+
if (crumbs.length < 2) return back;
|
|
659
|
+
var older = crumbs.slice(0, -1), steps = older.map(function (c, i) {
|
|
660
|
+
return '<span class="topbar-trail__step topbar-trail__step--' + (i ? 'mid' : 'first') + '"><a class="topbar-crumb" href="' +
|
|
661
|
+
esc(c.href) + '">' + esc(c.label) + '</a>' + sep + '</span>';
|
|
662
|
+
});
|
|
663
|
+
steps.splice(1, 0, '<span class="topbar-trail__more"><a class="topbar-crumb topbar-crumb--more" href="' + esc(older[0].href) + '" title="' +
|
|
664
|
+
esc(older.map(function (c) { return c.label; }).join(' › ')) + '" aria-label="' + esc(older[0].label) + '">…</a>' + sep + '</span>');
|
|
665
|
+
return '<nav class="topbar-trail' + (older.length > 1 ? ' topbar-trail--long' : '') + '" aria-label="Breadcrumb">' +
|
|
666
|
+
BACK_ICON.replace('<svg ', '<svg class="topbar-trail__mark" ') + steps.join('') + back + '</nav>';
|
|
620
667
|
}
|
|
621
|
-
// Back through history when the origin IS the previous entry
|
|
622
|
-
//
|
|
623
|
-
// stays the real address for a new tab or a lost history.
|
|
668
|
+
// Back through history when the origin IS the previous entry (the list keeps its
|
|
669
|
+
// scroll and filters); the href stays the real address for a new tab.
|
|
624
670
|
function onBackClick(e) {
|
|
625
671
|
if (!BACK || !BACK.viaReferrer || e.metaKey || e.ctrlKey || e.shiftKey || e.button > 0) return;
|
|
626
672
|
if (window.history && window.history.length > 1) { e.preventDefault(); window.history.back(); }
|
|
627
673
|
}
|
|
628
674
|
|
|
629
675
|
// ---------- full screen (task 1004327; standard since task 1004430) ----------
|
|
630
|
-
// One switch on EVERY shelled page
|
|
631
|
-
//
|
|
632
|
-
//
|
|
633
|
-
//
|
|
634
|
-
//
|
|
635
|
-
//
|
|
636
|
-
// The state is html[data-fullscreen="on"] — the data-theme / data-social
|
|
637
|
-
// pattern — so the chrome's hiding is style.css's, and a page that lays itself
|
|
638
|
-
// out against the chrome reads the same attribute.
|
|
639
|
-
//
|
|
640
|
-
// Remembered PER PAGE (`hall-fullscreen:<data-page>`): full screen is a choice
|
|
641
|
-
// about one surface, and the studio's must not follow the reader to the sky.
|
|
642
|
-
// Storage can throw in a private window; the chrome then just shows, which is
|
|
643
|
-
// the honest default. Because it is remembered, a page can OPEN in full screen,
|
|
644
|
-
// so entering it says once how to leave (the hint below) — task 1004430 found
|
|
645
|
-
// /thinking read as "stuck without its bars" when nothing did.
|
|
676
|
+
// One switch on EVERY shelled page hides the sidebar, top bar and foot; the same
|
|
677
|
+
// button (all that is left of the bar) and Escape bring them back. Opt out with
|
|
678
|
+
// <body data-fullscreen-switch="off">; the bare attribute means the page lays
|
|
679
|
+
// itself out for it (sky, studio), else it is `plain`. State: html[data-fullscreen="on"].
|
|
680
|
+
// Remembered PER PAGE (`hall-fullscreen:<data-page>`), so a page can OPEN in full
|
|
681
|
+
// screen and says once how to leave (task 1004430: /thinking read as "stuck").
|
|
646
682
|
var FULLSCREEN_KEY = 'hall-fullscreen:';
|
|
647
683
|
function fullscreenAttr() {
|
|
648
684
|
var b = document.body;
|
|
@@ -1354,6 +1390,7 @@
|
|
|
1354
1390
|
});
|
|
1355
1391
|
var back = document.getElementById('topbar-back');
|
|
1356
1392
|
if (back) back.addEventListener('click', onBackClick);
|
|
1393
|
+
window.addEventListener('hashchange', onTrailHash);
|
|
1357
1394
|
if (IS_INDEX) {
|
|
1358
1395
|
window.addEventListener('hashchange', function () { route(); });
|
|
1359
1396
|
}
|
|
@@ -203,7 +203,7 @@
|
|
|
203
203
|
</div>
|
|
204
204
|
</div>
|
|
205
205
|
|
|
206
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
206
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
207
207
|
<script src="/builders/palette.js" defer></script>
|
|
208
208
|
<script src="/builders/city-draw.js?v=2026-10-02-street1"></script>
|
|
209
209
|
<script src="/builders/street-draw.js?v=2026-10-02-street1"></script>
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
|
|
177
177
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
178
178
|
|
|
179
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
179
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
180
180
|
<script src="/builders/palette.js" defer></script>
|
|
181
181
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
182
182
|
<!-- The kit, for its ONE renderer: the full-size ship-time visual figure
|
|
@@ -1224,6 +1224,52 @@ html[data-fullscreen="on"][data-fullscreen-plain="on"] .app-content { padding-to
|
|
|
1224
1224
|
.topbar-back:hover { color: var(--ink); background: var(--rule-soft); }
|
|
1225
1225
|
.topbar-back svg { width: 16px; height: 16px; flex-shrink: 0; }
|
|
1226
1226
|
@media (max-width: 480px) { .topbar-back__label { display: none; } .topbar-back { padding: 0 8px; } }
|
|
1227
|
+
/* The trail (task 1004476): "‹ Goals › goal 12 › task 340", the last crumb
|
|
1228
|
+
being the Back link. On a phone the middle collapses to "…", and on a narrow
|
|
1229
|
+
one the bar's page name gives the trail its room (the page heading below
|
|
1230
|
+
still names the page). */
|
|
1231
|
+
.topbar-trail {
|
|
1232
|
+
display: inline-flex;
|
|
1233
|
+
align-items: center;
|
|
1234
|
+
flex-shrink: 0;
|
|
1235
|
+
margin-right: -4px;
|
|
1236
|
+
color: var(--ink-soft);
|
|
1237
|
+
font-size: 13px;
|
|
1238
|
+
white-space: nowrap;
|
|
1239
|
+
}
|
|
1240
|
+
.topbar-trail__mark { width: 16px; height: 16px; flex-shrink: 0; margin: 0 2px 0 6px; }
|
|
1241
|
+
.topbar-trail__step, .topbar-trail__more { display: inline-flex; align-items: center; }
|
|
1242
|
+
.topbar-crumb {
|
|
1243
|
+
display: inline-flex;
|
|
1244
|
+
align-items: center;
|
|
1245
|
+
min-height: 32px;
|
|
1246
|
+
padding: 0 6px;
|
|
1247
|
+
border-radius: var(--radius-pill);
|
|
1248
|
+
color: inherit;
|
|
1249
|
+
text-decoration: none;
|
|
1250
|
+
}
|
|
1251
|
+
.topbar-crumb:hover { color: var(--ink); background: var(--rule-soft); }
|
|
1252
|
+
.topbar-trail__sep { padding: 0 2px; color: var(--ink-faint); }
|
|
1253
|
+
.topbar-trail .topbar-back { padding: 0 10px 0 6px; }
|
|
1254
|
+
.topbar-trail .topbar-back svg { display: none; }
|
|
1255
|
+
.topbar-trail__more { display: none; }
|
|
1256
|
+
@media (max-width: 640px) {
|
|
1257
|
+
.topbar-trail__step--mid { display: none; }
|
|
1258
|
+
.topbar-trail--long .topbar-trail__more { display: inline-flex; }
|
|
1259
|
+
}
|
|
1260
|
+
@media (max-width: 480px) {
|
|
1261
|
+
.topbar-trail__step--first { display: none; }
|
|
1262
|
+
.topbar-trail .topbar-trail__more { display: inline-flex; }
|
|
1263
|
+
.topbar-trail .topbar-back__label { display: inline; }
|
|
1264
|
+
.topbar-trail .topbar-back { padding: 0 8px 0 6px; }
|
|
1265
|
+
.topbar-trail ~ .topbar-title { display: none; }
|
|
1266
|
+
}
|
|
1267
|
+
@media (max-width: 360px) {
|
|
1268
|
+
.topbar-trail__mark, .topbar-trail .topbar-trail__more, .topbar-trail .topbar-back__label { display: none; }
|
|
1269
|
+
.topbar-trail .topbar-back svg { display: block; }
|
|
1270
|
+
.topbar-trail .topbar-back { padding: 0 8px; }
|
|
1271
|
+
.topbar-trail ~ .topbar-title { display: block; }
|
|
1272
|
+
}
|
|
1227
1273
|
.zoom-toggle__pct {
|
|
1228
1274
|
font-size: 12px;
|
|
1229
1275
|
font-weight: 500;
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
|
|
55
55
|
<!-- The app shell (sidebar + top bar + footer). Dependency-free; runs at parse
|
|
56
56
|
time so the chrome exists before the deferred page scripts execute. -->
|
|
57
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
57
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
58
58
|
<!-- jump palette (Ctrl/Cmd-K). Optional by design: without it the shell's slot stays hidden. -->
|
|
59
59
|
<script src="/builders/palette.js" defer></script>
|
|
60
60
|
<!-- shared frontend toolkit (window.OTB) — loaded FIRST so task.js can pull from it. -->
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
</div>
|
|
139
139
|
</div>
|
|
140
140
|
|
|
141
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
141
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
142
142
|
<script src="/builders/palette.js" defer></script>
|
|
143
143
|
|
|
144
144
|
<script src="/builders/idea-objects.js?v=2026-09-27-split"></script>
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
|
|
143
143
|
<div id="toast" class="toast" role="status" aria-live="polite" data-visible="0"></div>
|
|
144
144
|
|
|
145
|
-
<script src="/builders/shell.js?v=2026-10-02-
|
|
145
|
+
<script src="/builders/shell.js?v=2026-10-02-trail"></script>
|
|
146
146
|
<script src="/builders/palette.js" defer></script>
|
|
147
147
|
<script src="/builders/dom-utils.js?v=2026-06-23-contrib"></script>
|
|
148
148
|
<script src="/builders/brand-holes.js?v=2026-09-29-aqfix"></script>
|