anentrypoint-design 0.0.167 → 0.0.169
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 +1 -1
- package/colors_and_type.css +14 -0
- package/dist/247420.css +83 -0
- package/dist/247420.js +55 -25
- package/package.json +9 -3
- package/src/community-app.js +1 -1
- package/src/components/chat.js +1 -1
- package/src/components/content.js +2 -2
- package/src/components/freddie.js +3 -3
- package/src/components/shell.js +2 -2
- package/src/index.js +3 -0
- package/src/kits/os/freddie/pages-core.js +3 -3
- package/src/kits/os/freddie/pages-os.js +1 -1
- package/src/kits/os/freddie/pages-tools.js +1 -1
- package/src/kits/os/freddie/routes.js +1 -1
- package/src/kits/os/theme.css +7 -14
- package/src/kits/spoint/index.js +8 -0
- package/src/kits/spoint/loading-screen.css +67 -0
- package/src/kits/spoint/loading-screen.js +75 -0
- package/src/markdown-cache-perf-test.js +2 -2
- package/src/page-html.js +46 -16
- package/src/web-components/ds-chat.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.169",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
"default": "./dist/247420.js"
|
|
12
12
|
},
|
|
13
13
|
"./css": "./dist/247420.css",
|
|
14
|
+
"./kits/spoint": {
|
|
15
|
+
"import": "./src/kits/spoint/index.js",
|
|
16
|
+
"default": "./src/kits/spoint/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./kits/spoint/loading-screen.js": "./src/kits/spoint/loading-screen.js",
|
|
19
|
+
"./kits/spoint/loading-screen.css": "./src/kits/spoint/loading-screen.css",
|
|
14
20
|
"./kits/os": {
|
|
15
21
|
"import": "./src/kits/os/index.js",
|
|
16
22
|
"default": "./src/kits/os/index.js"
|
|
@@ -56,8 +62,8 @@
|
|
|
56
62
|
"README.md"
|
|
57
63
|
],
|
|
58
64
|
"scripts": {
|
|
59
|
-
"
|
|
60
|
-
"
|
|
65
|
+
"lint:tokens": "node scripts/lint-tokens.mjs",
|
|
66
|
+
"build": "node scripts/build.mjs"
|
|
61
67
|
},
|
|
62
68
|
"repository": {
|
|
63
69
|
"type": "git",
|
package/src/community-app.js
CHANGED
|
@@ -186,7 +186,7 @@ export function mountCommunityApp(root, adapter = {}) {
|
|
|
186
186
|
h('nav', {},
|
|
187
187
|
h('a', { href: '../', title: 'Home', onclick: (e) => { if (A.goHome) { e.preventDefault(); A.goHome(); } } }, 'home'),
|
|
188
188
|
h('a', { href: '#', title: 'Servers', onclick: (e) => { e.preventDefault(); A.openServers && A.openServers(); } }, 'servers'),
|
|
189
|
-
h('a', { href: 'https://github.com/AnEntrypoint/zellous', target: '_blank', rel: 'noopener' }, 'source
|
|
189
|
+
h('a', { href: 'https://github.com/AnEntrypoint/zellous', target: '_blank', rel: 'noopener' }, 'source ->'),
|
|
190
190
|
),
|
|
191
191
|
),
|
|
192
192
|
MobileHeader({ channelType: ch.type || 'text', channelName: ch.name || '', onMenu: () => A.openMobileMenu && A.openMobileMenu(), onMembers: () => A.toggleMembers && A.toggleMembers() }),
|
package/src/components/chat.js
CHANGED
|
@@ -82,7 +82,7 @@ const PART_RENDERERS = {
|
|
|
82
82
|
h('span', { class: 'glyph', 'aria-hidden': 'true' }, '▤'),
|
|
83
83
|
h('span', { class: 'name' }, p.name || 'document.pdf'),
|
|
84
84
|
p.size != null ? h('span', { class: 'size' }, fmtBytes(p.size)) : null,
|
|
85
|
-
h('a', { class: 'open', href: p.src, target: '_blank', rel: 'noopener', 'aria-label': `open PDF: ${p.name || 'document.pdf'}` }, 'open
|
|
85
|
+
h('a', { class: 'open', href: p.src, target: '_blank', rel: 'noopener', 'aria-label': `open PDF: ${p.name || 'document.pdf'}` }, 'open ->')
|
|
86
86
|
),
|
|
87
87
|
h('embed', { src: p.src, type: 'application/pdf', 'aria-label': `PDF document: ${p.name || 'document.pdf'}` })),
|
|
88
88
|
file: (p) => h('a', { class: 'chat-file', href: p.src, target: '_blank', rel: 'noopener', download: p.name || true, 'aria-label': `download file: ${p.name || 'attachment'} (${p.kindLabel || (p.name || '').split('.').pop().toUpperCase()})` },
|
|
@@ -109,7 +109,7 @@ export function WorksList({ works = [], openedIndex = -1, onToggle }) {
|
|
|
109
109
|
Row({
|
|
110
110
|
code: w.code,
|
|
111
111
|
title: w.title, sub: w.sub,
|
|
112
|
-
meta: w.meta + ' ' + (isOpen ? '
|
|
112
|
+
meta: w.meta + ' ' + (isOpen ? '-' : '+'),
|
|
113
113
|
active: isOpen,
|
|
114
114
|
onClick: () => onToggle && onToggle(isOpen ? -1 : i)
|
|
115
115
|
}),
|
|
@@ -118,7 +118,7 @@ export function WorksList({ works = [], openedIndex = -1, onToggle }) {
|
|
|
118
118
|
h('p', { class: 'ds-work-body' }, w.body)
|
|
119
119
|
),
|
|
120
120
|
h('div', { class: 'ds-work-actions' },
|
|
121
|
-
Btn({ primary: true, href: w.href || '#', children: 'open
|
|
121
|
+
Btn({ primary: true, href: w.href || '#', children: 'open ->' }),
|
|
122
122
|
Btn({ href: w.source || '#', children: 'source' })
|
|
123
123
|
)
|
|
124
124
|
) : null
|
|
@@ -147,7 +147,7 @@ export const voice = makePage((ctx) => {
|
|
|
147
147
|
PageHeader({ eyebrow: 'freddie', title: 'voice', lede: 'voice surfaces', right: enabled ? Chip({ tone: 'ok', children: 'enabled' }) : Chip({ tone: 'neutral', children: 'not configured' }) }),
|
|
148
148
|
enabled
|
|
149
149
|
? section('backends', Table({ headers: ['capability', 'status'], rows: [['transcription', v.transcription ? Chip({ tone: 'ok', children: 'on' }) : Chip({ tone: 'neutral', children: 'off' })], ['tts', v.tts ? Chip({ tone: 'ok', children: 'on' }) : Chip({ tone: 'neutral', children: 'off' })]] }))
|
|
150
|
-
: section('status', emptyState('no voice backend wired in this build. configure a transcription/tts plugin to enable.'
|
|
150
|
+
: section('status', emptyState('no voice backend wired in this build. configure a transcription/tts plugin to enable.')),
|
|
151
151
|
];
|
|
152
152
|
};
|
|
153
153
|
});
|
|
@@ -405,7 +405,7 @@ export const config = makePage((ctx) => {
|
|
|
405
405
|
}
|
|
406
406
|
async function setSkin(name) {
|
|
407
407
|
ctx.set({ busy: true, note: null });
|
|
408
|
-
try { await api('/api/config', { method: 'POST', body: { skin: name } }); await load(); ctx.set({ note: { kind: 'success', msg: 'skin
|
|
408
|
+
try { await api('/api/config', { method: 'POST', body: { skin: name } }); await load(); ctx.set({ note: { kind: 'success', msg: 'skin -> ' + name } }); }
|
|
409
409
|
catch (e) { ctx.set({ note: { kind: 'error', msg: String(e.message || e) } }); }
|
|
410
410
|
ctx.set({ busy: false });
|
|
411
411
|
}
|
|
@@ -574,7 +574,7 @@ export const chains = makePage((ctx) => {
|
|
|
574
574
|
PageHeader({ eyebrow: 'freddie', title: 'chains', lede: 'acptoapi fallback chains', right: up ? Chip({ tone: 'ok', children: 'acptoapi up' }) : Chip({ tone: 'miss', children: 'acptoapi down' }) }),
|
|
575
575
|
noteAlert(s.note),
|
|
576
576
|
section('chains', Array.isArray(chainsList) && chainsList.length ? chainsList.map((c, i) => Row({
|
|
577
|
-
key: i, title: c.name || c, sub: Array.isArray(c.links) ? c.links.join('
|
|
577
|
+
key: i, title: c.name || c, sub: Array.isArray(c.links) ? c.links.join(' -> ') : '',
|
|
578
578
|
trailing: Btn({ danger: true, children: 'delete', onClick: () => del(c.name || c) }),
|
|
579
579
|
})) : emptyState('no chains defined')),
|
|
580
580
|
section('new chain',
|
package/src/components/shell.js
CHANGED
|
@@ -117,7 +117,7 @@ export function Topbar({ brand = '247420', leaf = '', items = [], active = '', o
|
|
|
117
117
|
h('input', { type: 'search', placeholder: search, 'aria-label': `search ${search}` })
|
|
118
118
|
) : null,
|
|
119
119
|
h('nav', { 'aria-label': 'main navigation' }, ...items.map(([label, href]) => {
|
|
120
|
-
const cleanLabel = String(label).replace('
|
|
120
|
+
const cleanLabel = String(label).replace(' ->', '');
|
|
121
121
|
return h('a', {
|
|
122
122
|
key: label,
|
|
123
123
|
href,
|
|
@@ -181,7 +181,7 @@ export function Status({ left = [], right = [] } = {}) {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// Toggle the mobile sidebar drawer. Pure-DOM because AppShell is stateless
|
|
184
|
-
// chrome; the class lives on .app-body and is read by the
|
|
184
|
+
// chrome; the class lives on .app-body and is read by the <=900px media query.
|
|
185
185
|
function toggleSide(open) {
|
|
186
186
|
const body = document.querySelector('.app-body');
|
|
187
187
|
if (!body) return;
|
package/src/index.js
CHANGED
|
@@ -74,6 +74,9 @@ export { applyTheme, getTheme, resolvedTheme, onThemeChange, initTheme,
|
|
|
74
74
|
export const h = webjsx.createElement;
|
|
75
75
|
export const applyDiff = webjsx.applyDiff;
|
|
76
76
|
|
|
77
|
+
// spoint kit paint surfaces (loading screen, HUD, editor chrome).
|
|
78
|
+
export { renderLoadingScreen } from './kits/spoint/loading-screen.js';
|
|
79
|
+
|
|
77
80
|
// Re-export freddie helpers so consumers can `import { FREDDIE_PAGES } from
|
|
78
81
|
// 'anentrypoint-design'` directly.
|
|
79
82
|
export {
|
|
@@ -51,9 +51,9 @@ export function makeCorePages(ctx) {
|
|
|
51
51
|
['open chat', "click 'chat' in sidebar — set a working directory and pick a skill"],
|
|
52
52
|
['pick skill', "software dev, research, planning — shown with descriptions"],
|
|
53
53
|
['pick model', "select a configured provider + model in the chat bar"],
|
|
54
|
-
['list tools', '/tools in chat
|
|
55
|
-
['set api key', 'keys tab
|
|
56
|
-
['add cron', 'cron tab
|
|
54
|
+
['list tools', '/tools in chat -> tools tab'],
|
|
55
|
+
['set api key', 'keys tab -> click chip to set value'],
|
|
56
|
+
['add cron', 'cron tab -> form'],
|
|
57
57
|
] }) }),
|
|
58
58
|
Panel({ title: 'host', children: Receipt({ rows: Object.entries(health).map(([k, v]) => [k, String(v)]) }) }),
|
|
59
59
|
];
|
|
@@ -43,7 +43,7 @@ export function makeOsPages(ctx) {
|
|
|
43
43
|
return [
|
|
44
44
|
Kpi({ items: [[list.length, 'paths'], [instance.id, 'instance']] }),
|
|
45
45
|
Panel({ title: 'paths', count: list.length, children: list.length === 0
|
|
46
|
-
? EmptyState({ text: 'empty fs', glyph: '
|
|
46
|
+
? EmptyState({ text: 'empty fs', glyph: '◫' })
|
|
47
47
|
: pre(list.join('\n')) }),
|
|
48
48
|
];
|
|
49
49
|
},
|
|
@@ -115,7 +115,7 @@ export function makeToolsPages(ctx) {
|
|
|
115
115
|
if (typeof h0.pi.env.set === 'function') { h0.pi.env.set(k.key, v); rerender(); }
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
|
-
Chip({ tone: k.set ? 'ok' : 'miss', children: k.key + (k.set ? '
|
|
118
|
+
Chip({ tone: k.set ? 'ok' : 'miss', children: k.key + (k.set ? ' [x]' : ' [ ]') })
|
|
119
119
|
));
|
|
120
120
|
return [
|
|
121
121
|
Kpi({ items: [[setCount, 'set'], [list.length - setCount, 'missing'], [list.length, 'total known']] }),
|
|
@@ -20,5 +20,5 @@ export const OS_ROUTE_DEFS = [
|
|
|
20
20
|
{ path: 'os-instances', label: 'instances', glyph: '◫' },
|
|
21
21
|
{ path: 'os-windows', label: 'windows', glyph: '▭' },
|
|
22
22
|
{ path: 'os-x', label: 'x-server', glyph: '✕' },
|
|
23
|
-
{ path: 'os-fs', label: 'fs', glyph: '
|
|
23
|
+
{ path: 'os-fs', label: 'fs', glyph: '◫' },
|
|
24
24
|
];
|
package/src/kits/os/theme.css
CHANGED
|
@@ -443,9 +443,9 @@ html, body {
|
|
|
443
443
|
* --os-* aliases above consume the canonical semantic tokens (--bg/--fg/
|
|
444
444
|
* --accent), and colors_and_type.css already drives [data-theme] (paper/ink/
|
|
445
445
|
* auto, with color-scheme + --danger tuning) and [data-accent] (green/purple/
|
|
446
|
-
* mascot). Re-declaring
|
|
447
|
-
* drift (ink
|
|
448
|
-
*
|
|
446
|
+
* mascot). Re-declaring the os surface or accent tokens per theme here only
|
|
447
|
+
* re-introduced drift (ink vs canonical ink; purple vs canonical purple).
|
|
448
|
+
* Density bar-height is genuinely OS-shell-specific, so it stays;
|
|
449
449
|
* --os-accent-tint maps to the canonical accent tint. */
|
|
450
450
|
:root { --os-accent-tint: var(--accent-tint); }
|
|
451
451
|
:root[data-density="compact"] { --os-bar-h: 28px; --os-tile-pad: 6px; --os-gap: 6px; }
|
|
@@ -463,18 +463,11 @@ html, body {
|
|
|
463
463
|
* silently mutated the base theme for EVERY portfolio consumer (canonical
|
|
464
464
|
* --paper is #F6F5F1; thebird wanted #F5F0E4). The warm-paper variant is now a
|
|
465
465
|
* named preset [data-theme="thebird"] a consumer opts into, leaving the base
|
|
466
|
-
* theme untouched.
|
|
467
|
-
*
|
|
466
|
+
* theme untouched. The [data-theme="thebird"] COLOR preset now lives in the
|
|
467
|
+
* canonical colors_and_type.css (a first-class swappable theme); only the
|
|
468
|
+
* OS-shell chrome (bar geometry, typography alias) stays here scoped to
|
|
469
|
+
* .ds-247420.
|
|
468
470
|
* ============================================================ */
|
|
469
|
-
[data-theme="thebird"] {
|
|
470
|
-
color-scheme: light;
|
|
471
|
-
--paper: #F5F0E4;
|
|
472
|
-
--paper-2: #EFE9DB;
|
|
473
|
-
--paper-3: #E3DAC7;
|
|
474
|
-
--bg: var(--paper); --bg-2: var(--paper-2); --bg-3: var(--paper-3);
|
|
475
|
-
--fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
|
|
476
|
-
--accent: var(--green); --accent-fg: var(--paper);
|
|
477
|
-
}
|
|
478
471
|
.ds-247420 {
|
|
479
472
|
--ff-ui: var(--ff-body);
|
|
480
473
|
/* uniform bar height: 22px button + 6px+6px padding = 34px */
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// spoint kit — paint surfaces for the spoint game client (loading screen,
|
|
2
|
+
// HUD, editor chrome). Each render fn returns {node, ...controls, dispose};
|
|
3
|
+
// the consumer owns state/events, this kit owns layout + classes. Surfaced
|
|
4
|
+
// through the main bundle entry so spoint can import directly from unpkg.
|
|
5
|
+
|
|
6
|
+
export { renderLoadingScreen } from './loading-screen.js';
|
|
7
|
+
|
|
8
|
+
export const themeUrl = new URL('./loading-screen.css', import.meta.url).href;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* Loading-screen kit styles. Scoped under .ds-247420 at build time.
|
|
2
|
+
All colors reference design tokens (no raw literals) per the token-lint gate. */
|
|
3
|
+
.sp-loading {
|
|
4
|
+
position: fixed;
|
|
5
|
+
inset: 0;
|
|
6
|
+
z-index: 10000;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
background: var(--bg);
|
|
11
|
+
color: var(--fg);
|
|
12
|
+
font-family: var(--ff-mono);
|
|
13
|
+
transition: opacity var(--dur-slow) var(--ease);
|
|
14
|
+
}
|
|
15
|
+
.sp-loading-fade { opacity: 0; pointer-events: none; }
|
|
16
|
+
.sp-loading-container {
|
|
17
|
+
width: min(420px, 86vw);
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
gap: 20px;
|
|
21
|
+
}
|
|
22
|
+
.sp-loading-header h1 {
|
|
23
|
+
margin: 0;
|
|
24
|
+
font-family: var(--ff-display);
|
|
25
|
+
font-size: var(--fs-h2);
|
|
26
|
+
letter-spacing: 0.04em;
|
|
27
|
+
}
|
|
28
|
+
.sp-loading-label {
|
|
29
|
+
margin: 4px 0 0;
|
|
30
|
+
color: var(--fg-2);
|
|
31
|
+
font-size: var(--fs-body);
|
|
32
|
+
}
|
|
33
|
+
.sp-loading-bars { display: flex; flex-direction: column; gap: 10px; }
|
|
34
|
+
.sp-loading-bar-row {
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: 88px 1fr 44px;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 10px;
|
|
39
|
+
}
|
|
40
|
+
.sp-loading-bar-name {
|
|
41
|
+
color: var(--fg-3);
|
|
42
|
+
font-size: var(--fs-small, 11px);
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
letter-spacing: 0.1em;
|
|
45
|
+
}
|
|
46
|
+
.sp-loading-bar-track {
|
|
47
|
+
height: 6px;
|
|
48
|
+
border-radius: 3px;
|
|
49
|
+
background: var(--bg-3);
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
}
|
|
52
|
+
.sp-loading-bar-fill {
|
|
53
|
+
height: 100%;
|
|
54
|
+
width: 0%;
|
|
55
|
+
background: var(--accent);
|
|
56
|
+
transition: width var(--dur-base) var(--ease);
|
|
57
|
+
}
|
|
58
|
+
.sp-loading-bar-pct {
|
|
59
|
+
color: var(--fg-2);
|
|
60
|
+
font-size: var(--fs-small, 11px);
|
|
61
|
+
text-align: right;
|
|
62
|
+
}
|
|
63
|
+
.sp-loading-detail {
|
|
64
|
+
min-height: 16px;
|
|
65
|
+
color: var(--fg-3);
|
|
66
|
+
font-size: var(--fs-small, 11px);
|
|
67
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Loading-screen paint surface for the spoint game client.
|
|
2
|
+
// renderLoadingScreen({brand, label}) -> { node, setLabel, setDownload,
|
|
3
|
+
// setProcessing, setDetail, hide, dispose }. The consumer (spoint
|
|
4
|
+
// LoadingManager) owns progress events; this module owns layout + classes.
|
|
5
|
+
// Two progress bars (download, processing), a label, and a detail line.
|
|
6
|
+
|
|
7
|
+
export function renderLoadingScreen(opts = {}) {
|
|
8
|
+
const { brand = 'spoint', label = 'Connecting...' } = opts;
|
|
9
|
+
|
|
10
|
+
const node = document.createElement('div');
|
|
11
|
+
node.className = 'sp-loading ds-247420';
|
|
12
|
+
node.dataset.component = 'loading-screen';
|
|
13
|
+
|
|
14
|
+
const container = document.createElement('div');
|
|
15
|
+
container.className = 'sp-loading-container';
|
|
16
|
+
|
|
17
|
+
const header = document.createElement('div');
|
|
18
|
+
header.className = 'sp-loading-header';
|
|
19
|
+
const title = document.createElement('h1');
|
|
20
|
+
title.textContent = brand;
|
|
21
|
+
const labelEl = document.createElement('p');
|
|
22
|
+
labelEl.className = 'sp-loading-label';
|
|
23
|
+
labelEl.textContent = label;
|
|
24
|
+
header.append(title, labelEl);
|
|
25
|
+
|
|
26
|
+
const bars = document.createElement('div');
|
|
27
|
+
bars.className = 'sp-loading-bars';
|
|
28
|
+
|
|
29
|
+
const mkBar = (name) => {
|
|
30
|
+
const row = document.createElement('div');
|
|
31
|
+
row.className = 'sp-loading-bar-row';
|
|
32
|
+
const nameEl = document.createElement('span');
|
|
33
|
+
nameEl.className = 'sp-loading-bar-name';
|
|
34
|
+
nameEl.textContent = name;
|
|
35
|
+
const track = document.createElement('div');
|
|
36
|
+
track.className = 'sp-loading-bar-track';
|
|
37
|
+
const fill = document.createElement('div');
|
|
38
|
+
fill.className = 'sp-loading-bar-fill';
|
|
39
|
+
track.appendChild(fill);
|
|
40
|
+
const pct = document.createElement('span');
|
|
41
|
+
pct.className = 'sp-loading-bar-pct';
|
|
42
|
+
pct.textContent = '0%';
|
|
43
|
+
row.append(nameEl, track, pct);
|
|
44
|
+
return { row, fill, pct };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const dl = mkBar('Download');
|
|
48
|
+
const proc = mkBar('Processing');
|
|
49
|
+
bars.append(dl.row, proc.row);
|
|
50
|
+
|
|
51
|
+
const detail = document.createElement('div');
|
|
52
|
+
detail.className = 'sp-loading-detail';
|
|
53
|
+
|
|
54
|
+
container.append(header, bars, detail);
|
|
55
|
+
node.appendChild(container);
|
|
56
|
+
|
|
57
|
+
const setBar = (bar, percent) => {
|
|
58
|
+
bar.fill.style.width = percent + '%';
|
|
59
|
+
bar.pct.textContent = Math.round(percent) + '%';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
node,
|
|
64
|
+
setLabel: (text) => { labelEl.textContent = text; },
|
|
65
|
+
setDownload: (percent) => setBar(dl, percent),
|
|
66
|
+
setProcessing: (percent) => setBar(proc, percent),
|
|
67
|
+
setDetail: (text) => { detail.textContent = text; },
|
|
68
|
+
hide: async () => {
|
|
69
|
+
node.classList.add('sp-loading-fade');
|
|
70
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
71
|
+
node.remove();
|
|
72
|
+
},
|
|
73
|
+
dispose: () => node.remove(),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -158,9 +158,9 @@ async function runAllTests() {
|
|
|
158
158
|
const speedup = (10000 + initStats.initMs.markdown + initStats.initMs.prism) / (mdStats.avg * 100 + initStats.initMs.markdown + initStats.initMs.prism);
|
|
159
159
|
console.log(`Performance improvement: ~${speedup.toFixed(1)}x faster`);
|
|
160
160
|
|
|
161
|
-
console.log('\
|
|
161
|
+
console.log('\nPASS All tests completed successfully');
|
|
162
162
|
} catch (err) {
|
|
163
|
-
console.error('\
|
|
163
|
+
console.error('\nFAIL Test failed:', err.message);
|
|
164
164
|
console.error(err.stack);
|
|
165
165
|
process.exit(1);
|
|
166
166
|
}
|
package/src/page-html.js
CHANGED
|
@@ -99,15 +99,32 @@ ${cssLink}
|
|
|
99
99
|
.page-body h1 { margin-top: 0 } .page-body h2 { margin-top: var(--space-5, 32px) } .page-body h3 { margin-top: var(--space-4, 24px) }
|
|
100
100
|
.page-body > * + * { margin-top: var(--space-3, 16px) }
|
|
101
101
|
.page-body pre { margin: var(--space-3, 16px) 0; background: var(--panel-2); padding: var(--space-3, 16px); border-radius: var(--r-1, 10px); overflow-x: auto }
|
|
102
|
-
/* .app-stage owns inter-block rhythm via grid gap; sections/hero must not double it
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
/* .app-stage owns inter-block rhythm via grid gap; sections/hero must not double it.
|
|
103
|
+
These selectors carry !important because this inline block loads before the
|
|
104
|
+
unpkg CSS bundle, which would otherwise win on load-order for equal specificity. */
|
|
105
|
+
.ds-247420 .app-stage > .ds-hero { margin: 0 !important; padding: var(--space-4, 24px) 0 0 !important; max-width: none !important; gap: var(--space-4, 24px) !important }
|
|
106
|
+
.ds-247420 .app-stage > .ds-section { margin: 0 !important }
|
|
105
107
|
.app-stage .row + .row { margin-top: var(--space-1, 4px) }
|
|
106
108
|
.app-stage .ds-section .row { margin-top: var(--space-2, 8px) }
|
|
107
109
|
.app-stage .ds-section > p.ds-lede { margin: 0 0 var(--space-3, 16px); max-width: var(--measure, 68ch); color: var(--fg-2) }
|
|
108
110
|
.row-benefit { font-style: italic; color: var(--fg-3); font-size: var(--fs-sm); margin-top: var(--space-1, 4px) }
|
|
109
111
|
.ds-row-arrow { margin-left: auto; opacity: .5; transition: opacity var(--dur-snap, 80ms) var(--ease) }
|
|
110
112
|
a.row:hover .ds-row-arrow { opacity: 1 }
|
|
113
|
+
/* hero stat strip — all badges as a wrapping inline rhythm, not one empty panel */
|
|
114
|
+
.ds-hero-stats { display: flex; flex-wrap: wrap; gap: var(--space-3, 16px) var(--space-5, 32px); margin-top: var(--space-2, 8px) }
|
|
115
|
+
.ds-hero-stat { display: flex; align-items: baseline; gap: var(--space-2, 8px) }
|
|
116
|
+
.ds-hero-stat-n { font-family: var(--ff-body); font-weight: 700; font-size: var(--fs-lg, 18px); color: var(--fg) }
|
|
117
|
+
.ds-hero-stat-l { font-size: var(--fs-sm, 15px); color: var(--fg-3) }
|
|
118
|
+
/* feature rows — single-column stack with a rail accent (the dashboard .row grid
|
|
119
|
+
forces a 3-col code/title/meta layout that mangles title+desc+benefit) */
|
|
120
|
+
.ds-feature { position: relative; padding: var(--space-3, 16px) var(--space-4, 24px); background: var(--bg, #fff); border-radius: var(--r-2, 14px); display: grid; gap: var(--space-1, 4px) }
|
|
121
|
+
.ds-feature::before { content: ''; position: absolute; left: 0; top: var(--space-2, 8px); bottom: var(--space-2, 8px); width: 3px; border-radius: 3px; background: var(--rail-color, var(--rule-strong)) }
|
|
122
|
+
.ds-feature.rail-green { --rail-color: var(--green) } .ds-feature.rail-purple { --rail-color: var(--purple) } .ds-feature.rail-mascot { --rail-color: var(--mascot) }
|
|
123
|
+
.ds-feature.rail-sun { --rail-color: var(--sun) } .ds-feature.rail-flame { --rail-color: var(--flame) } .ds-feature.rail-sky { --rail-color: var(--sky) }
|
|
124
|
+
.ds-feature + .ds-feature { margin-top: var(--space-2, 8px) }
|
|
125
|
+
.ds-feature-title { font-weight: 600; font-size: var(--fs-lg, 18px); color: var(--fg) }
|
|
126
|
+
.ds-feature-desc { font-size: var(--fs-sm, 15px); color: var(--fg-2); line-height: 1.5 }
|
|
127
|
+
.ds-feature-benefit { font-style: italic; font-size: var(--fs-sm, 15px); color: var(--fg-3); margin-top: var(--space-1, 4px) }
|
|
111
128
|
</style>
|
|
112
129
|
<script id="__site__" type="application/json">${JSON.stringify(pageData).replace(/</g, '\\u003c')}</script>
|
|
113
130
|
${headExtra}
|
|
@@ -121,24 +138,37 @@ const RAILS = ['rail-green', 'rail-purple', 'rail-mascot', 'rail-sun', 'rail-fla
|
|
|
121
138
|
|
|
122
139
|
function heroNode(hero) {
|
|
123
140
|
if (!hero) return null;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
141
|
+
const badges = Array.isArray(hero.badges) ? hero.badges.filter(Boolean) : [];
|
|
142
|
+
const badgeRow = badges.length
|
|
143
|
+
? h('div', { class: 'ds-hero-stats' }, ...badges.map((b, i) =>
|
|
144
|
+
h('span', { key: i, class: 'ds-hero-stat' },
|
|
145
|
+
h('strong', { class: 'ds-hero-stat-n' }, String(b.label != null ? b.label : b)),
|
|
146
|
+
b.desc ? h('span', { class: 'ds-hero-stat-l' }, String(b.desc)) : null,
|
|
147
|
+
)))
|
|
148
|
+
: null;
|
|
149
|
+
return h('div', { class: 'ds-hero' },
|
|
150
|
+
hero.eyebrow ? h('span', { class: 'eyebrow' }, hero.eyebrow) : null,
|
|
151
|
+
h('h1', { class: 'ds-hero-title' }, hero.heading || hero.title || data.title),
|
|
152
|
+
(hero.body || hero.subheading) ? h('p', { class: 'ds-hero-body' },
|
|
153
|
+
hero.body || hero.subheading,
|
|
154
|
+
hero.accent ? h('span', { class: 'ds-hero-accent' }, ' ' + hero.accent) : null,
|
|
155
|
+
) : null,
|
|
156
|
+
Array.isArray(hero.ctas) && hero.ctas.length
|
|
157
|
+
? h('div', { class: 'ds-hero-actions' }, ...hero.ctas.map((c, i) =>
|
|
158
|
+
h('a', { key: i, class: i === 0 ? 'btn btn-accent' : 'btn btn-ghost', href: c.href || '#' }, c.label || c.cta || 'go')))
|
|
159
|
+
: null,
|
|
160
|
+
badgeRow,
|
|
161
|
+
);
|
|
132
162
|
}
|
|
133
163
|
|
|
134
164
|
function sectionNode(sec, idx) {
|
|
135
165
|
const rail = RAILS[idx % RAILS.length];
|
|
136
166
|
const features = sec.features || sec.items || [];
|
|
137
167
|
const rows = features.map((f, i) => {
|
|
138
|
-
const kids = [h('
|
|
139
|
-
if (f.desc) kids.push(h('div', { key: 'd', class: '
|
|
140
|
-
if (f.benefit) kids.push(h('div', { key: 'b', class: '
|
|
141
|
-
return h('div', { key: i, class: '
|
|
168
|
+
const kids = [h('div', { key: 't', class: 'ds-feature-title' }, String(f.name || ''))];
|
|
169
|
+
if (f.desc) kids.push(h('div', { key: 'd', class: 'ds-feature-desc', innerHTML: String(f.desc).replace(/\`([^\`]+)\`/g, '<code>$1</code>') }));
|
|
170
|
+
if (f.benefit) kids.push(h('div', { key: 'b', class: 'ds-feature-benefit' }, String(f.benefit)));
|
|
171
|
+
return h('div', { key: i, class: 'ds-feature ' + rail }, ...kids);
|
|
142
172
|
});
|
|
143
173
|
return C.Section({
|
|
144
174
|
title: sec.name || sec.title || sec.id,
|
|
@@ -161,7 +191,7 @@ function examplesNode(examples) {
|
|
|
161
191
|
h('span', { key: 't', class: 'title' }, String(e.label || e.name || e.href || '')),
|
|
162
192
|
];
|
|
163
193
|
if (e.desc) kids.push(h('span', { key: 'm', class: 'meta dim' }, ' — ' + e.desc));
|
|
164
|
-
kids.push(h('span', { key: 'a', class: 'ds-row-arrow' }, '
|
|
194
|
+
kids.push(h('span', { key: 'a', class: 'ds-row-arrow' }, '->'));
|
|
165
195
|
return h('a', { key: i, class: 'row ' + rail, href: e.href || '#' }, ...kids);
|
|
166
196
|
}),
|
|
167
197
|
});
|