anentrypoint-design 0.0.398 → 0.0.400
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/chat.css +72 -0
- package/dist/247420.css +81 -0
- package/dist/247420.js +21 -21
- package/package.json +15 -1
- package/scripts/lint-glyphs.mjs +5 -1
- package/scripts/lint-null-children.mjs +7 -1
- package/src/components/editor-primitives/json-viewer.js +15 -12
- package/src/components/files/grid.js +29 -0
- package/src/components/sessions/dashboard.js +5 -4
- package/src/components/sessions/session-card.js +24 -6
- package/src/css/app-shell/primitives.css +9 -0
- package/src/markdown-cache.js +14 -2
- package/types/components.d.ts +2931 -0
- package/types/index.d.ts +106 -0
package/package.json
CHANGED
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.400",
|
|
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",
|
|
7
7
|
"module": "./dist/247420.js",
|
|
8
|
+
"types": "./types/index.d.ts",
|
|
9
|
+
"sideEffects": [
|
|
10
|
+
"*.css",
|
|
11
|
+
"./src/index.js",
|
|
12
|
+
"./src/styles.js",
|
|
13
|
+
"./src/markdown-cache.js",
|
|
14
|
+
"./src/components/chat/stats.js",
|
|
15
|
+
"./src/web-components/freddie-chat.js",
|
|
16
|
+
"./dist/247420.js"
|
|
17
|
+
],
|
|
8
18
|
"exports": {
|
|
9
19
|
".": {
|
|
20
|
+
"types": "./types/index.d.ts",
|
|
10
21
|
"import": "./dist/247420.js",
|
|
11
22
|
"default": "./dist/247420.js"
|
|
12
23
|
},
|
|
@@ -72,6 +83,7 @@
|
|
|
72
83
|
"files": [
|
|
73
84
|
"dist",
|
|
74
85
|
"src",
|
|
86
|
+
"types",
|
|
75
87
|
"scripts/lint-glyphs.mjs",
|
|
76
88
|
"scripts/lint-null-children.mjs",
|
|
77
89
|
"scripts/lint-shared.mjs",
|
|
@@ -97,6 +109,8 @@
|
|
|
97
109
|
"sitemap": "node scripts/generate-sitemap.mjs",
|
|
98
110
|
"docs:components": "node scripts/generate-component-docs.mjs",
|
|
99
111
|
"lint:component-docs": "node scripts/generate-component-docs.mjs --check",
|
|
112
|
+
"types:components": "node scripts/generate-component-types.mjs",
|
|
113
|
+
"lint:component-types": "node scripts/generate-component-types.mjs --check",
|
|
100
114
|
"generate:ui-kits": "node scripts/generate-ui-kit-scaffolds.mjs",
|
|
101
115
|
"generate:preview-index": "node scripts/generate-preview-index.mjs",
|
|
102
116
|
"a11y": "node scripts/a11y-audit.mjs",
|
package/scripts/lint-glyphs.mjs
CHANGED
|
@@ -18,7 +18,11 @@ const root = path.resolve(__dirname, '..');
|
|
|
18
18
|
// Directories scanned recursively for source files. dist/ is generated,
|
|
19
19
|
// node_modules/ is vendored, vendor/ is third-party (webjsx), .gm/ is the
|
|
20
20
|
// plugkit spool — none are hand-authored design surfaces.
|
|
21
|
-
|
|
21
|
+
// `preview` added 2026-07-28. It had been missing while EXEMPT_FILES below
|
|
22
|
+
// already carried a `preview/icons-unicode.html` entry — an exemption for a
|
|
23
|
+
// directory the walk never entered, i.e. dead code that read as coverage. The
|
|
24
|
+
// preview/ tree ships and is exactly where glyphs accumulate unnoticed.
|
|
25
|
+
const SCAN_DIRS = ['src', 'ui_kits', 'slides', 'site', 'preview'];
|
|
22
26
|
const SCAN_EXT = new Set(['.js', '.mjs', '.css', '.html']);
|
|
23
27
|
// The bundled root CSS files (app-shell.css, chat.css, etc.) are the design
|
|
24
28
|
// system's shipped styling but live at the repo root, outside SCAN_DIRS — they
|
|
@@ -22,7 +22,13 @@ import { walkFiles } from './lint-shared.mjs';
|
|
|
22
22
|
|
|
23
23
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
24
24
|
const root = path.resolve(__dirname, '..');
|
|
25
|
-
|
|
25
|
+
// `ui_kits`, `site`, `preview`, `slides` added 2026-07-28. The bug this gate
|
|
26
|
+
// catches is a webjsx applyDiff crash on a children array holding a null/false
|
|
27
|
+
// hole, so its true scope is "everywhere h() is called" — and h() is called in
|
|
28
|
+
// 20 files outside src/ (every ui_kits/*/app.js, site/theme.mjs,
|
|
29
|
+
// preview/data-density.js). Scanning only src/ meant the gate never looked at
|
|
30
|
+
// the consumer code most likely to hand-roll a conditional child.
|
|
31
|
+
const SCAN_DIRS = ['src', 'ui_kits', 'site', 'preview', 'slides'];
|
|
26
32
|
const SCAN_EXT = new Set(['.js', '.mjs']);
|
|
27
33
|
const SKIP_DIRS = new Set(['node_modules', 'vendor']);
|
|
28
34
|
|
|
@@ -107,18 +107,21 @@ export function JsonViewer({ value, emptyText = 'no data', maxHeight, mode = 'pl
|
|
|
107
107
|
else { try { text = JSON.stringify(value, null, 2); knownJson = text != null; parsed = value; } catch { text = String(value); } }
|
|
108
108
|
if (!text) return h('div', { class: 'ds-ep-json ds-ep-json-empty' }, emptyText);
|
|
109
109
|
const style = maxHeight ? ('max-height:' + maxHeight) : null;
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
110
|
+
// Every viewer is a scroll container, so these are UNCONDITIONAL. The
|
|
111
|
+
// `maxHeight` prop only overrides a height the stylesheet already sets:
|
|
112
|
+
// `.ds-ep-json` carries `max-height: 300px; overflow-y: auto` in
|
|
113
|
+
// editor-primitives.css, so a viewer rendered with no prop at all still
|
|
114
|
+
// clips and still scrolls. Gating the attributes on the prop therefore
|
|
115
|
+
// missed the common case — measured live: a prop-less viewer reported
|
|
116
|
+
// scrollHeight 1265 against clientHeight 300 while sitting at tabindex -1.
|
|
117
|
+
//
|
|
118
|
+
// Clipped content reachable by wheel but not by keyboard is WCAG 2.1.1
|
|
119
|
+
// Keyboard, axe's `scrollable-region-focusable`. tabindex puts the box in
|
|
120
|
+
// the tab order and arrow keys then scroll it natively; a bare focusable
|
|
121
|
+
// region with no name is its own violation, so it is labelled. `group`
|
|
122
|
+
// rather than `region` so a page rendering several viewers does not gain a
|
|
123
|
+
// landmark each.
|
|
124
|
+
const scrollable = { tabindex: '0', role: 'group', 'aria-label': 'JSON, scrollable' };
|
|
122
125
|
if (!knownJson && (mode === 'highlight' || mode === 'tree')) {
|
|
123
126
|
try { parsed = JSON.parse(text); knownJson = true; } catch { /* swallow: not JSON — render plain */ }
|
|
124
127
|
}
|
|
@@ -23,6 +23,35 @@ const h = webjsx.createElement;
|
|
|
23
23
|
// CAP and a "show N more" row, mirroring the History tab's "load N older".
|
|
24
24
|
const FILE_GRID_CAP = 200;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* The directory listing.
|
|
28
|
+
*
|
|
29
|
+
* `loading` and `busy` are NOT two spellings of one state -- they are the two
|
|
30
|
+
* halves of this SDK's standing distinction, and FileGrid is the component
|
|
31
|
+
* that takes both because it is the one place both are in play at once:
|
|
32
|
+
*
|
|
33
|
+
* loading -- a DATA FETCH is in flight. Owns which SHAPE renders: with no
|
|
34
|
+
* rows yet it is a cold load and the whole grid is replaced by
|
|
35
|
+
* FileSkeleton; with rows already on screen it is a refresh and
|
|
36
|
+
* the existing rows stay mounted and dim (is-refreshing), because
|
|
37
|
+
* flashing a populated directory back to shimmer reads as data
|
|
38
|
+
* loss.
|
|
39
|
+
* busy -- a USER ACTION is in flight (a rename/move/delete round-trip).
|
|
40
|
+
* Owns INTERACTIVITY, not shape: it is forwarded to each FileRow
|
|
41
|
+
* as `busy`, which disables that row's open + mutation controls
|
|
42
|
+
* so a second click cannot fire the same mutation twice.
|
|
43
|
+
*
|
|
44
|
+
* A grid can be `busy` while not `loading` (a delete is posting, rows fully
|
|
45
|
+
* rendered) and `loading` while not `busy` (a plain refresh). Passing one for
|
|
46
|
+
* the other is a real bug, not a style choice, so they are deliberately not
|
|
47
|
+
* merged and neither is an alias of the other.
|
|
48
|
+
*
|
|
49
|
+
* @param {Array} [files=[]] - the directory entries to render.
|
|
50
|
+
* @param {boolean} [loading=false] - a data fetch is in flight (skeleton when cold, dim when refreshing).
|
|
51
|
+
* @param {boolean} [busy] - a user-initiated mutation is in flight; disables every row's controls. Per-entry `f.busy` is used when this is not passed.
|
|
52
|
+
* @param {string} [emptyText='No files here yet'] - copy for the empty/filtered-miss state.
|
|
53
|
+
* @param {'list'|'compact'|'thumb'} [density='list'] - row density; 'thumb' switches to the multi-column cell grid.
|
|
54
|
+
*/
|
|
26
55
|
export function FileGrid({ files = [], onOpen, onAction, onUp, emptyText = 'No files here yet', emptyAction,
|
|
27
56
|
sort, filter, loading = false,
|
|
28
57
|
shown, onShowMore, actions, busy,
|
|
@@ -55,7 +55,8 @@ export function SessionDashboard({ sessions = [], onStop, onOpen, onView, onStop
|
|
|
55
55
|
sort, filter, errorsOnly = false, onErrorsOnly,
|
|
56
56
|
selectable = false, selected, onToggleSelect, onSelectAll, onClearSelection,
|
|
57
57
|
activeSid, streamState,
|
|
58
|
-
emptyText = 'No live sessions', emptyAction, offline = false
|
|
58
|
+
emptyText = 'No live sessions', emptyAction, offline = false,
|
|
59
|
+
density = 'comfortable' } = {}) {
|
|
59
60
|
if (offline) {
|
|
60
61
|
return h('div', { class: 'ds-dash-state ds-dash-state-error', role: 'status' }, 'Backend offline — live sessions unavailable');
|
|
61
62
|
}
|
|
@@ -171,7 +172,7 @@ export function SessionDashboard({ sessions = [], onStop, onOpen, onView, onStop
|
|
|
171
172
|
const grouped = !sort || !sort.value || sort.value === 'status';
|
|
172
173
|
const cardOf = (s) => h('div', { key: s.sid, role: 'listitem' },
|
|
173
174
|
SessionCard({ session: s, onStop, onOpen, onView, active: s.sid === activeSid,
|
|
174
|
-
selectable, selected: selSet.has(s.sid), onToggleSelect }));
|
|
175
|
+
selectable, selected: selSet.has(s.sid), onToggleSelect, density }));
|
|
175
176
|
// ONE stable body wrapper across every state (empty / grouped / flat), with
|
|
176
177
|
// KEYED children - the ConversationList stable-keyed-body rule. Diffing
|
|
177
178
|
// happens on the children, never by swapping the container's shape.
|
|
@@ -193,9 +194,9 @@ export function SessionDashboard({ sessions = [], onStop, onOpen, onView, onStop
|
|
|
193
194
|
].filter((b) => b.rows.length);
|
|
194
195
|
bodyKids = buckets.map((b) => h('div', { key: 'grp' + b.key, class: 'ds-dash-group', role: 'group', 'aria-label': b.label + ' sessions' },
|
|
195
196
|
h('div', { key: 'gl', class: 'ds-dash-group-label' }, b.label + ' · ' + b.rows.length),
|
|
196
|
-
h('div', { key: 'gg', class: 'ds-dash-grid', role: 'list', 'aria-label': b.label + ' sessions' }, ...b.rows.map(cardOf))));
|
|
197
|
+
h('div', { key: 'gg', class: 'ds-dash-grid' + (density === 'compact' ? ' is-compact' : ''), role: 'list', 'aria-label': b.label + ' sessions' }, ...b.rows.map(cardOf))));
|
|
197
198
|
} else {
|
|
198
|
-
bodyKids = [h('div', { key: 'flat', class: 'ds-dash-grid', role: 'list', 'aria-label': 'live sessions' }, ...sessions.map(cardOf))];
|
|
199
|
+
bodyKids = [h('div', { key: 'flat', class: 'ds-dash-grid' + (density === 'compact' ? ' is-compact' : ''), role: 'list', 'aria-label': 'live sessions' }, ...sessions.map(cardOf))];
|
|
199
200
|
}
|
|
200
201
|
const body = h('div', { key: 'body', class: 'ds-dash-groups' }, ...bodyKids);
|
|
201
202
|
return h('div', { class: 'ds-dash' }, header, body);
|
|
@@ -28,9 +28,21 @@ const h = webjsx.createElement;
|
|
|
28
28
|
// the card heading so the rail row and its dashboard card share one identity.
|
|
29
29
|
// `session.elapsedMs` (raw ms) is formatted internally via fmtDuration; the
|
|
30
30
|
// pre-formatted `elapsed` string remains as a legacy fallback.
|
|
31
|
+
// `density` trades vertical space for scannability, the same list/compact axis
|
|
32
|
+
// FileGrid already exposes:
|
|
33
|
+
// 'comfortable' (default) — the full card: title, head, meta, per-card actions.
|
|
34
|
+
// 'compact' — one line per session. Measured on a real 16-session
|
|
35
|
+
// dashboard the comfortable card renders 208px tall,
|
|
36
|
+
// so a 439px viewport shows two sessions; the point of
|
|
37
|
+
// a command center is scanning many at once. Compact
|
|
38
|
+
// keeps every FACT (status, agent, cwd, elapsed,
|
|
39
|
+
// activity) and drops only the per-card action row,
|
|
40
|
+
// which is reachable by opening the session.
|
|
31
41
|
export function SessionCard({ session = {}, onStop, onOpen, onView, active = false,
|
|
32
|
-
selectable = false, selected = false, onToggleSelect
|
|
42
|
+
selectable = false, selected = false, onToggleSelect,
|
|
43
|
+
density = 'comfortable' } = {}) {
|
|
33
44
|
const s = session;
|
|
45
|
+
const compact = density === 'compact';
|
|
34
46
|
const st = s.stopping ? 'stopping' : (s.status === 'error' ? 'error' : (s.status === 'stale' ? 'stale' : 'running'));
|
|
35
47
|
// The stat line composes elapsed + live counter; the activity line carries the
|
|
36
48
|
// last-activity time and the current tool so a card shows MOTION, not just a
|
|
@@ -47,7 +59,7 @@ export function SessionCard({ session = {}, onStop, onOpen, onView, active = fal
|
|
|
47
59
|
s.currentTool ? 'running: ' + s.currentTool : null,
|
|
48
60
|
s.lastActivity ? 'last ' + s.lastActivity : null,
|
|
49
61
|
].filter(Boolean);
|
|
50
|
-
const cls = 'ds-dash-card is-' + st + (active ? ' is-active' : '') + (selected ? ' is-selected' : '') + (s.external ? ' is-external' : '') + (s.isNew ? ' is-new' : '');
|
|
62
|
+
const cls = 'ds-dash-card is-' + st + (compact ? ' is-compact' : '') + (active ? ' is-active' : '') + (selected ? ' is-selected' : '') + (s.external ? ' is-external' : '') + (s.isNew ? ' is-new' : '');
|
|
51
63
|
// EVERY children array is filter(Boolean)'d: webjsx applyDiff crashes
|
|
52
64
|
// (reading 'key') on a bare null among VElement siblings, so a null cwd /
|
|
53
65
|
// model / external flag must never reach a positional child slot.
|
|
@@ -84,9 +96,15 @@ export function SessionCard({ session = {}, onStop, onOpen, onView, active = fal
|
|
|
84
96
|
onClick: () => !s.stopping && onStop(s),
|
|
85
97
|
children: [Icon('square', { size: 14 }), h('span', {}, s.stopping ? 'stopping…' : 'stop')] }) : null,
|
|
86
98
|
].filter(Boolean));
|
|
99
|
+
// Compact keeps head + meta on ONE row and drops the action group; the title
|
|
100
|
+
// rides as the element's own accessible name (already set below) rather than
|
|
101
|
+
// taking a line of its own, so nothing is lost, only re-laid-out.
|
|
102
|
+
const children = compact
|
|
103
|
+
? [head, meta].filter(Boolean)
|
|
104
|
+
: [
|
|
105
|
+
s.title ? h('div', { class: 'ds-dash-title', title: s.title }, s.title) : null,
|
|
106
|
+
head, meta, actions,
|
|
107
|
+
].filter(Boolean);
|
|
87
108
|
return h('div', { class: cls, role: 'group', 'aria-label': 'session ' + (s.title || s.agent || s.sid), 'aria-current': active ? 'true' : null },
|
|
88
|
-
...
|
|
89
|
-
s.title ? h('div', { class: 'ds-dash-title', title: s.title }, s.title) : null,
|
|
90
|
-
head, meta, actions,
|
|
91
|
-
].filter(Boolean));
|
|
109
|
+
...children);
|
|
92
110
|
}
|
|
@@ -165,6 +165,15 @@
|
|
|
165
165
|
.chip.tone-wip, .chip.tone-neutral {
|
|
166
166
|
background: var(--bg-3); color: var(--fg-2);
|
|
167
167
|
}
|
|
168
|
+
/* tone-dim was applied by five kits (aicat, project_page, signin, system_primer,
|
|
169
|
+
terminal) with no rule anywhere, so a "dim" chip rendered byte-identical to a
|
|
170
|
+
plain one — measured at rgb(234,230,218) on rgb(31,31,38), same opacity. It is
|
|
171
|
+
the recede-into-the-row tone: the tier-3 foreground on the same recessed
|
|
172
|
+
surface tone-wip uses, which is quieter than the default --fg-2 without
|
|
173
|
+
dropping to an opacity fade that would take the border and background with it. */
|
|
174
|
+
.chip.tone-dim {
|
|
175
|
+
background: var(--bg-3); color: var(--fg-3);
|
|
176
|
+
}
|
|
168
177
|
.chip.tone-purple { background: var(--purple-tint); color: var(--purple-deep); }
|
|
169
178
|
.chip.tone-mascot { background: var(--mascot-tint); color: var(--ink); }
|
|
170
179
|
.chip.tone-sun, .chip.tone-yellow {
|
package/src/markdown-cache.js
CHANGED
|
@@ -23,6 +23,7 @@ let _initPromise = null;
|
|
|
23
23
|
let _renderCache = new Map();
|
|
24
24
|
let _stats = {
|
|
25
25
|
markdownInitMs: 0,
|
|
26
|
+
totalInitMs: 0,
|
|
26
27
|
prismInitMs: 0,
|
|
27
28
|
renderCount: 0,
|
|
28
29
|
renderTimes: [],
|
|
@@ -59,8 +60,13 @@ export async function initializeCachesEagerly() {
|
|
|
59
60
|
})(),
|
|
60
61
|
]);
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
console.debug
|
|
63
|
+
// Recorded, not printed. This is library code, so an unconditional
|
|
64
|
+
// console.debug writes into every consuming application's console on
|
|
65
|
+
// every init. The same numbers are already live-inspectable through
|
|
66
|
+
// window.__debug['markdown-cache'] (registered at the bottom of this
|
|
67
|
+
// file), which is the repo's own observability channel and the one a
|
|
68
|
+
// consumer can actually opt into.
|
|
69
|
+
_stats.totalInitMs = performance.now() - startTime;
|
|
64
70
|
|
|
65
71
|
return { markdown: mdOk, prism: prismOk };
|
|
66
72
|
})();
|
|
@@ -140,6 +146,11 @@ export function getCacheStats() {
|
|
|
140
146
|
initMs: {
|
|
141
147
|
markdown: _stats.markdownInitMs,
|
|
142
148
|
prism: _stats.prismInitMs,
|
|
149
|
+
// Wall-clock for the whole init, which is not the sum of the two
|
|
150
|
+
// above: they run concurrently under Promise.all, so total is the
|
|
151
|
+
// slower of the pair plus overhead. Previously only ever printed
|
|
152
|
+
// to console.debug; exposed here so it is inspectable instead.
|
|
153
|
+
total: _stats.totalInitMs,
|
|
143
154
|
},
|
|
144
155
|
renderStats: {
|
|
145
156
|
count: _stats.renderCount,
|
|
@@ -171,6 +182,7 @@ export function resetCacheState() {
|
|
|
171
182
|
_renderCache.clear();
|
|
172
183
|
_stats = {
|
|
173
184
|
markdownInitMs: 0,
|
|
185
|
+
totalInitMs: 0,
|
|
174
186
|
prismInitMs: 0,
|
|
175
187
|
renderCount: 0,
|
|
176
188
|
renderTimes: [],
|