anentrypoint-design 0.0.216 → 0.0.218
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/app-shell.css +6 -0
- package/chat.css +9 -0
- package/dist/247420.css +14 -0
- package/dist/247420.js +11 -11
- package/package.json +1 -1
- package/src/components/agent-chat.js +1 -1
- package/src/components/shell.js +29 -16
- package/src/markdown.js +11 -5
- package/src/page-html.js +4 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.218",
|
|
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",
|
|
@@ -184,7 +184,7 @@ export function AgentChat(props = {}) {
|
|
|
184
184
|
const msgHasBody = (m) => !!(m.content || (Array.isArray(m.parts) && m.parts.length));
|
|
185
185
|
const lastMsgLastPart = lastMsg && Array.isArray(lastMsg.parts) && lastMsg.parts.length ? lastMsg.parts[lastMsg.parts.length - 1] : null;
|
|
186
186
|
const showWorkingTail = busy && lastMsg && lastMsg.role === 'assistant' && msgHasBody(lastMsg)
|
|
187
|
-
&& lastMsgLastPart && lastMsgLastPart.kind === 'tool' &&
|
|
187
|
+
&& lastMsgLastPart && lastMsgLastPart.kind === 'tool' && lastMsgLastPart.status === 'running';
|
|
188
188
|
const rows = messages.slice(msgStart).map((m, wi) => {
|
|
189
189
|
const i = wi + msgStart; // absolute index — streaming/caret/actions logic keys off the real lastIdx
|
|
190
190
|
const isAssistant = m.role === 'assistant';
|
package/src/components/shell.js
CHANGED
|
@@ -164,27 +164,38 @@ const ICON_PATHS = {
|
|
|
164
164
|
// rather than an h() vnode. Same path table, same viewBox/stroke contract as
|
|
165
165
|
// Icon(); use innerHTML = iconMarkup(name). Keeps the icon paths upstream so
|
|
166
166
|
// raw-DOM call sites never reintroduce decorative glyph literals.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
// The single SVG attribute contract (viewBox/stroke/linecap…) shared by both
|
|
168
|
+
// the markup-string and the vnode renderers below, so the icon shape is defined
|
|
169
|
+
// once. Insertion order is the serialized attribute order iconMarkup emits.
|
|
170
|
+
function iconAttrs(name, size) {
|
|
171
|
+
return {
|
|
172
|
+
class: 'ds-icon ds-icon-' + name,
|
|
173
|
+
width: String(size), height: String(size), viewBox: '0 0 24 24',
|
|
174
|
+
fill: 'none', stroke: 'currentColor', 'stroke-width': 'var(--ds-icon-stroke, 1.6)',
|
|
175
|
+
'stroke-linecap': 'round', 'stroke-linejoin': 'round', 'aria-hidden': 'true',
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// Normalize the (name) | ({name,size}) call shapes both renderers accept.
|
|
179
|
+
function iconArgs(name, size) {
|
|
170
180
|
if (name && typeof name === 'object') ({ name, size = 16 } = name);
|
|
181
|
+
return { name, size };
|
|
182
|
+
}
|
|
183
|
+
// Raw-DOM consumers (no webjsx render in scope) need the SVG as a markup string
|
|
184
|
+
// rather than an h() vnode. Same path table + attr contract as Icon(); use
|
|
185
|
+
// innerHTML = iconMarkup(name). Keeps the icon paths upstream so raw-DOM call
|
|
186
|
+
// sites never reintroduce decorative glyph literals.
|
|
187
|
+
export function iconMarkup(name, { size = 16 } = {}) {
|
|
188
|
+
({ name, size } = iconArgs(name, size));
|
|
171
189
|
const inner = ICON_PATHS[name];
|
|
172
190
|
if (!inner) return '';
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
' stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + inner + '</svg>';
|
|
191
|
+
const attrs = Object.entries(iconAttrs(name, size)).map(([k, v]) => `${k}="${v}"`).join(' ');
|
|
192
|
+
return `<svg ${attrs}>${inner}</svg>`;
|
|
176
193
|
}
|
|
177
194
|
export function Icon(name, { size = 16 } = {}) {
|
|
178
|
-
|
|
195
|
+
({ name, size } = iconArgs(name, size));
|
|
179
196
|
const inner = ICON_PATHS[name];
|
|
180
197
|
if (!inner) return h('span', { class: 'glyph', 'aria-hidden': 'true' }, '');
|
|
181
|
-
return h('svg', {
|
|
182
|
-
class: 'ds-icon ds-icon-' + name,
|
|
183
|
-
width: String(size), height: String(size), viewBox: '0 0 24 24',
|
|
184
|
-
fill: 'none', stroke: 'currentColor', 'stroke-width': 'var(--ds-icon-stroke, 1.6)',
|
|
185
|
-
'stroke-linecap': 'round', 'stroke-linejoin': 'round', 'aria-hidden': 'true',
|
|
186
|
-
dangerouslySetInnerHTML: { __html: inner }
|
|
187
|
-
});
|
|
198
|
+
return h('svg', { ...iconAttrs(name, size), dangerouslySetInnerHTML: { __html: inner } });
|
|
188
199
|
}
|
|
189
200
|
|
|
190
201
|
export function Topbar({ brand = '247420', leaf = '', items = [], active = '', onNav, search } = {}) {
|
|
@@ -467,6 +478,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
467
478
|
const keepPaneTrack = stableFrame && !hasPane;
|
|
468
479
|
const railIsCollapsed = wsCollapsed('rail', railCollapsed);
|
|
469
480
|
const paneIsCollapsed = hasPane ? wsCollapsed('pane', paneCollapsed) : true;
|
|
481
|
+
const sessionsIsCollapsed = wsCollapsed('sessions', false);
|
|
470
482
|
const shellCls = 'ws-shell'
|
|
471
483
|
+ (railIsCollapsed ? ' ws-rail-collapsed' : '')
|
|
472
484
|
+ ((hasPane || keepPaneTrack) ? '' : ' ws-no-pane')
|
|
@@ -513,8 +525,9 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
513
525
|
// full-width thread/grid). Hidden on mobile via CSS.
|
|
514
526
|
hasSessions ? h('button', {
|
|
515
527
|
class: 'ws-desktop-toggle ws-sessions-toggle', type: 'button',
|
|
516
|
-
'aria-label': '
|
|
517
|
-
|
|
528
|
+
'aria-label': sessionsIsCollapsed ? 'expand conversations' : 'collapse conversations',
|
|
529
|
+
title: sessionsIsCollapsed ? 'expand conversations' : 'collapse conversations',
|
|
530
|
+
'aria-expanded': sessionsIsCollapsed ? 'false' : 'true', onclick: () => toggleWs('sessions'),
|
|
518
531
|
}, Icon('chevron-left')) : null,
|
|
519
532
|
h('div', { class: 'ws-crumb-main' }, crumb),
|
|
520
533
|
// Desktop-only context-pane collapse, on the same crumb-level
|
package/src/markdown.js
CHANGED
|
@@ -10,8 +10,12 @@ let _purify = null;
|
|
|
10
10
|
let _failedAt = 0;
|
|
11
11
|
const RETRY_BACKOFF_MS = 30000;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// Pin to exact semver so the CDN cannot silently swap code under us.
|
|
14
|
+
// SRI cannot be applied to dynamic ESM imports in browsers (no importmap
|
|
15
|
+
// integrity support at design time); pinning the version is the best available
|
|
16
|
+
// mitigation for CDN-supply-chain risk on these two dependencies.
|
|
17
|
+
const MARKED_URL = 'https://cdn.jsdelivr.net/npm/marked@15.0.12/+esm';
|
|
18
|
+
const PURIFY_URL = 'https://cdn.jsdelivr.net/npm/dompurify@3.2.6/+esm';
|
|
15
19
|
|
|
16
20
|
// True while the markdown stack is unavailable (escaped-fallback rendering).
|
|
17
21
|
// Consumers (markdown-cache) use this to avoid caching degraded output.
|
|
@@ -40,7 +44,9 @@ export async function ensureReady() {
|
|
|
40
44
|
return _ready;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
// The single HTML-entity escape for the whole SDK (full set incl. quotes, so it
|
|
48
|
+
// is safe in attribute contexts too). page-html.js re-exports this as `escape`.
|
|
49
|
+
export function escapeHtml(s) {
|
|
44
50
|
return String(s).replace(/[&<>"']/g, (c) => ({
|
|
45
51
|
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
46
52
|
})[c]);
|
|
@@ -50,7 +56,7 @@ export async function renderMarkdown(src) {
|
|
|
50
56
|
const ok = await ensureReady();
|
|
51
57
|
if (!ok) return escapeHtml(src).replace(/\n/g, '<br>');
|
|
52
58
|
const raw = _marked.parse(String(src));
|
|
53
|
-
return _purify.sanitize(raw);
|
|
59
|
+
return _purify.sanitize(raw, { FORCE_BODY: true });
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
// Sanitize already-rendered HTML before it touches innerHTML. For any surface
|
|
@@ -60,5 +66,5 @@ export async function renderMarkdown(src) {
|
|
|
60
66
|
export async function sanitizeHtml(html) {
|
|
61
67
|
const ok = await ensureReady();
|
|
62
68
|
if (!ok) return escapeHtml(html);
|
|
63
|
-
return _purify.sanitize(String(html));
|
|
69
|
+
return _purify.sanitize(String(html), { FORCE_BODY: true });
|
|
64
70
|
}
|
package/src/page-html.js
CHANGED
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
// cssHref, headExtra,
|
|
17
17
|
// })
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
19
|
+
// Single source of HTML escaping lives in markdown.js (full entity set). Kept
|
|
20
|
+
// the `escape` export name for backward compatibility with any consumer.
|
|
21
|
+
import { escapeHtml } from './markdown.js';
|
|
22
|
+
export const escape = escapeHtml;
|
|
22
23
|
|
|
23
24
|
export function inlineMd(s) {
|
|
24
25
|
return s
|