@bongos/core 1.19.400 → 1.19.401
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 +22 -22
- package/docs/copy-inventory.md +233 -232
- package/docs/copy-registry.json +293 -284
- package/docs/design/projects-hub-direction-v2.md +38 -0
- package/docs/recipes/ui-look-before-you-ship.md +1 -1
- package/modules/ui-design/kit/lib.js +6 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/public-landing/assets/cosmos.css +88 -35
- package/public-landing/index.html +13 -15
- package/public-landing/index.probes.json +8 -5
- package/public-landing/projects.html +23 -13
- package/public-landing/projects.probes.json +17 -10
- package/public-landing/projects.states.json +1 -1
- package/src/module-api.js +3 -1
- package/tests/landing_page.mjs +8 -4
- package/tests/projects_hub.mjs +28 -1
- package/tests/ui_design_kit.mjs +5 -4
package/src/module-api.js
CHANGED
|
@@ -1240,8 +1240,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
1240
1240
|
// landed since 1.19.398 with no explicit bump. run 33201243958. (task 1002620)
|
|
1241
1241
|
// 1.19.400 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1242
1242
|
// landed since 1.19.399 with no explicit bump. run 33201979306. (task 1002620)
|
|
1243
|
+
// 1.19.401 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
1244
|
+
// landed since 1.19.400 with no explicit bump. run 33205015717. (task 1002620)
|
|
1243
1245
|
// ---------------------------------------------------------------------------
|
|
1244
|
-
const CORE_VERSION = '1.19.
|
|
1246
|
+
const CORE_VERSION = '1.19.401'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
1245
1247
|
|
|
1246
1248
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
1247
1249
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/landing_page.mjs
CHANGED
|
@@ -475,14 +475,17 @@ test('the bar is markup: the mark, the Projects trigger, the mode glyph, the sig
|
|
|
475
475
|
assert.match(PAGE_CSS, /\.topbar\{position:relative;z-index:50;height:var\(--top-h\);display:flex;align-items:center;gap:22px;\s*padding:0 26px;background:var\(--bg\);border-bottom:1px solid var\(--rule\)\}/, 'the page ground closed by one hairline, z-index unified with the hub');
|
|
476
476
|
});
|
|
477
477
|
|
|
478
|
-
test('the Projects band deep-links the hub\'s views; About and Docs
|
|
478
|
+
test('the Projects band deep-links the hub\'s views; About and Docs are footer links, not band items; no item is current here', () => {
|
|
479
479
|
const body = HTML.split('<body>')[1].split('<script>')[0];
|
|
480
480
|
assert.match(body, /<div class="menuBand" id="menuProjects" data-menu="projects" hidden>/);
|
|
481
481
|
assert.match(body, /<a class="bandT" href="\/projects\?view=map">Sky<\/a>/);
|
|
482
482
|
assert.match(body, /<a class="bandT" href="\/projects\?view=map&sub=table">Table<\/a>/, 'the Table item lands on the table (the hub reads sub=table on boot)');
|
|
483
483
|
assert.match(body, /<li class="bandCell" id="mineCell" hidden><a class="bandT" href="\/projects\?view=mine">Your projects<\/a>/, 'member-gated: hidden until the session resolves');
|
|
484
484
|
assert.match(body, /<a class="bandT" href="\/projects\?view=new">New project<\/a>/);
|
|
485
|
-
|
|
485
|
+
// About and Docs are site pages, not project views (owner, 2026-08-28; task 1003332):
|
|
486
|
+
// they left the band for the footer row, beside Privacy / Terms / Contact
|
|
487
|
+
assert.doesNotMatch(body, /bandMore|<a class="bandT" href="#about">|<a class="bandT" href="\/docs">/, 'About and Docs are not in the Projects band');
|
|
488
|
+
assert.match(body, /<a href="#about">About<\/a>\s*<a href="\/docs">Docs<\/a>\s*<a href="\/privacy">Privacy<\/a>/, 'About and Docs open the footer row');
|
|
486
489
|
assert.match(body, /<section class="band" id="about">/, 'About has a real anchor: the lifecycle band');
|
|
487
490
|
assert.doesNotMatch(body.split('<main')[0], /aria-current/, 'the landing is none of those views');
|
|
488
491
|
// the profile band: the person, My projects, the deferred slot, Sign out as the honest anchor
|
|
@@ -496,9 +499,10 @@ test('the Projects band deep-links the hub\'s views; About and Docs sit under a
|
|
|
496
499
|
assert.ok(body.includes('>' + copy + '<'), `"${copy}" is only reachable with scripting on`);
|
|
497
500
|
}
|
|
498
501
|
// the menu container is .menuBand: .band is this page's own content sections
|
|
499
|
-
|
|
502
|
+
// the bands OVERLAY the page (task 1003332): absolute at the bar's height, so the hero never reflows
|
|
503
|
+
assert.match(PAGE_CSS, /\.menuBand\{position:absolute;left:0;right:0;top:var\(--top-h\);z-index:49;background:var\(--bg-card\);border-bottom:1px solid var\(--rule\);/);
|
|
500
504
|
assert.doesNotMatch(PAGE_CSS, /\.band\{[^}]*animation:bandIn/, 'the menu rule never lands on the content bands');
|
|
501
|
-
assert.
|
|
505
|
+
assert.doesNotMatch(PAGE_CSS, /\.bandMore/, 'the About/Docs rung left the sheet with the markup');
|
|
502
506
|
});
|
|
503
507
|
|
|
504
508
|
test('the bands are one disclosure: Escape returns focus, arrows cycle, Tab out closes, one closes the other', () => {
|
package/tests/projects_hub.mjs
CHANGED
|
@@ -49,7 +49,14 @@ test('the Projects band carries the views; Home is gone and the mark is the way
|
|
|
49
49
|
assert.match(HUB, /href="\?view=map" data-nav="map" data-sub="sky" aria-current="page">Sky<\/a>/);
|
|
50
50
|
assert.match(HUB, /href="\?view=map&sub=table" data-nav="map" data-sub="table">Table<\/a>/);
|
|
51
51
|
assert.match(SCRIPT, /get\('sub'\) === 'table'\) setSub\('table'\);/, 'the Table deep link lands on the table');
|
|
52
|
-
|
|
52
|
+
// setView rewrites the URL to ?view=<v>; the boot query must be captured BEFORE it
|
|
53
|
+
// runs or sub=table is gone by the time it is read (task 1003332)
|
|
54
|
+
assert.match(SCRIPT, /var bootQ = new URLSearchParams\(location\.search\);\s*setView\(viewFromUrl\(\)\);[\s\S]{0,400}?if \(bootQ\.get\('sub'\) === 'table'\) setSub\('table'\);/, 'the boot query is read once, before setView');
|
|
55
|
+
// About and Docs are site pages, not project views (owner, 2026-08-28; task 1003332):
|
|
56
|
+
// they left the band for the footer row, beside Privacy / Terms / Contact
|
|
57
|
+
assert.doesNotMatch(HUB, /bandMore|<a class="bandT" href="\/#about">|<a class="bandT" href="\/docs">/, 'About and Docs are not in the Projects band');
|
|
58
|
+
assert.match(HUB, /<nav class="footNav" aria-label="Site"><a href="\/#about">About<\/a><a href="\/docs">Docs<\/a><a href="\/privacy">Privacy<\/a>/, 'About and Docs open the footer row');
|
|
59
|
+
assert.doesNotMatch(COSMOS, /\.bandMore/, 'the About/Docs rung left cosmos with the markup');
|
|
53
60
|
assert.doesNotMatch(HUB, /id="sub-sky"|id="sub-table"|class="toolbar"|class="seg"/, 'the toolbar and its seg are retired');
|
|
54
61
|
assert.doesNotMatch(SCRIPT, /dataset\.nav === 'home'/, 'no dead Home branch in the router');
|
|
55
62
|
assert.match(SCRIPT, /if \(a\.dataset\.sub\) setSub\(a\.dataset\.sub\);/, 'a band item may pick the map sub-view');
|
|
@@ -138,6 +145,10 @@ test('the bands: one disclosure, two instances — Escape returns focus, the car
|
|
|
138
145
|
assert.match(HUB, /<div class="menuBand" id="menuProjects" data-menu="projects" hidden>/);
|
|
139
146
|
assert.match(HUB, /<div class="menuBand" id="menuProfile" data-menu="profile" hidden>/);
|
|
140
147
|
assert.doesNotMatch(HUB, /role="menu"|aria-haspopup/, 'plain links in a disclosure — announced as what ships');
|
|
148
|
+
// the bands OVERLAY the page (owner, 2026-08-28; task 1003332): absolute against the
|
|
149
|
+
// document at the bar's height, so opening one never reflows the sky, the table or the footer
|
|
150
|
+
assert.match(COSMOS, /\.menuBand\{position:absolute;left:0;right:0;top:var\(--top-h\);z-index:49;background:var\(--bg-card\);border-bottom:1px solid var\(--rule\);/, 'a band is a layer under the bar, never a push');
|
|
151
|
+
assert.doesNotMatch(COSMOS, /PUSHES the page/, 'the sheet no longer describes the push-down');
|
|
141
152
|
assert.match(SCRIPT, /function closeMenus\(\) \{[\s\S]*?if \(inside && trig\) trig\.focus\(\);/, 'focus restoration is a property of the close, not of one caller');
|
|
142
153
|
assert.match(SCRIPT, /if \(ev\.key === 'Escape' && !openBand\(\)\) closeCard\(\);/, 'the card yields Escape to an open band');
|
|
143
154
|
assert.match(SCRIPT, /function setView\(v, focus\) \{[\s\S]*?\$\('qWrap'\)\.hidden = \$\('qToggle'\)\.hidden = \(v !== 'map'\);/, 'the search hides off the map in the router');
|
|
@@ -525,6 +536,22 @@ test('no sort control is offered for a column that cannot sort', () => {
|
|
|
525
536
|
}
|
|
526
537
|
});
|
|
527
538
|
|
|
539
|
+
test('the table is in the world: a masthead, then ledger rows — no panel, no shadow, the accent only on the row\'s door (task 1003332)', () => {
|
|
540
|
+
// the owner's pick from three rendered treatments: the view title in the display
|
|
541
|
+
// voice and one chrome object; the title is two words ("every project", the owner cut ", as rows")
|
|
542
|
+
assert.match(HUB, /<div class="tblMast">\s*<h2 class="tblTitle">every project<\/h2>\s*<span class="mastObj" aria-hidden="true"><\/span>\s*<\/div>\s*<table class="tbl">/, 'one masthead ahead of the table');
|
|
543
|
+
assert.doesNotMatch(HUB, /tblMast--t[123]|data-tbl|mastCallouts|mastField/, 'the render round\'s switch and the unpicked mastheads left with the pick');
|
|
544
|
+
assert.match(COSMOS, /\.tbl\{width:100%;border-collapse:collapse;background:none;\}/, 'the rows sit on the page ground — no card');
|
|
545
|
+
assert.doesNotMatch((COSMOS.match(/\.tbl\{[^}]*\}/) || [''])[0], /border-radius|box-shadow/, 'no radius, no shadow on the table');
|
|
546
|
+
assert.match(COSMOS, /\.tbl td\{padding:17px 14px;border-bottom:1px solid var\(--rule-soft\);/, 'ledger rows: hairlines');
|
|
547
|
+
assert.match(COSMOS, /\.tbl tbody tr:hover td\{border-bottom-color:var\(--ink-faint\);\}/, 'hover is the hairline taking ink, not an accent tint');
|
|
548
|
+
assert.match(COSMOS, /\.rowGo\{[^}]*color:var\(--accent-deep\);text-decoration:underline;/, 'the row\'s door is accent text');
|
|
549
|
+
assert.match(HUB, /<a class="rowGo" href="\/">Open →<\/a>/, 'the self row\'s door');
|
|
550
|
+
assert.match(SCRIPT, /'<a class="rowGo" href="' \+ esc\(safeHttpUrl\(p\.origin\)\)/, 'the generated rows\' door');
|
|
551
|
+
assert.match(COSMOS, /\.mastObj\{display:block;--dia:clamp\(96px,10vw,132px\);[^}]*background-image:var\(--plate-set-cut\);/, 'the object is the set\'s small bead by token, in both modes');
|
|
552
|
+
assert.doesNotMatch(COSMOS, /mix-blend-mode:var\(--mast/, 'the cutout needs no blend — the view wrap is a stacking context');
|
|
553
|
+
});
|
|
554
|
+
|
|
528
555
|
test('every live column keeps its styling — .colType included since task 1002772', () => {
|
|
529
556
|
for (const live of ['.tbl .num', '.tbl .tags', '.colTags', '.colType', '.typeTag']) {
|
|
530
557
|
assert.ok(COSMOS.includes(live), `${live} styles a column that renders real data`);
|
package/tests/ui_design_kit.mjs
CHANGED
|
@@ -85,10 +85,11 @@ test('auditFloors names each floor a render breaks, and says nothing about a cle
|
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
test('expectProblems compares every expectation the vocabulary allows', () => {
|
|
88
|
-
const facts = { ...clean(), expanded: ['projTrig'], dialog: true, sel: { '#a': true, '#b': false }, activeId: 'x', activeText: 'Sky', param: { view: 'mine' }, attr: ['dark'], text: ['Table'], href: ['/docs'], count: [3], checked: false, value: ['demo'], hasClass: [true] };
|
|
89
|
-
assert.deepEqual(lib.expectProblems(facts, { expanded: true, dialog: true, visible: ['#a'], hidden: ['#b'], open: '#a', closed: '#b', activeId: 'x', activeText: 'Sky', expandedIds: ['projTrig'], param: { view: 'mine' }, attr: [['html', 'data-mode', 'dark']], text: [['h1', 'Table']], href: [['a', '/docs']], count: [['li', 3]], value: [['#q', 'demo']], hasClass: [['#w', 'is-open']] }), []);
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const facts = { ...clean(), expanded: ['projTrig'], dialog: true, sel: { '#a': true, '#b': false }, activeId: 'x', activeText: 'Sky', param: { view: 'mine' }, attr: ['dark'], text: ['Table'], href: ['/docs'], count: [3], checked: false, value: ['demo'], hasClass: [true], top: [64] };
|
|
89
|
+
assert.deepEqual(lib.expectProblems(facts, { expanded: true, dialog: true, visible: ['#a'], hidden: ['#b'], open: '#a', closed: '#b', activeId: 'x', activeText: 'Sky', expandedIds: ['projTrig'], param: { view: 'mine' }, attr: [['html', 'data-mode', 'dark']], text: [['h1', 'Table']], href: [['a', '/docs']], count: [['li', 3]], value: [['#q', 'demo']], hasClass: [['#w', 'is-open']], top: [['main', 64]] }), []);
|
|
90
|
+
// `top` is how a probe proves an overlay did not push the page (task 1003332)
|
|
91
|
+
const p = lib.expectProblems(facts, { expanded: false, dialog: false, visible: ['#b'], hidden: ['#a'], activeText: 'Table', param: { view: null }, count: [['li', 5]], checked: '#c', hasClass: [['#w', 'is-open', false]], noOverflow: true, top: [['main', 185]] });
|
|
92
|
+
for (const needle of ['expected no expanded trigger', 'expected no visible dialog', 'expected visible: #b', 'expected hidden: #a', 'active text "Sky", expected "Table"', '?view=mine, expected null', '3 × li, expected 5', '#c is not checked', 'still has class "is-open"', 'main top 64px, expected 185px']) {
|
|
92
93
|
assert.ok(p.some((x) => x.includes(needle)), `missing: ${needle} in ${p.join(' | ')}`);
|
|
93
94
|
}
|
|
94
95
|
});
|