anentrypoint-design 0.0.280 → 0.0.281
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/app-shell.css +69 -8
- package/colors_and_type.css +1 -1
- package/community.css +5 -5
- package/dist/247420.css +75 -14
- package/dist/247420.js +12 -12
- package/package.json +1 -1
- package/src/components/chat.js +37 -2
- package/src/components/shell.js +8 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.281",
|
|
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",
|
package/src/components/chat.js
CHANGED
|
@@ -161,6 +161,9 @@ export function injectCodeCopy(container) {
|
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
const MD_STREAM_THROTTLE_MS = 120;
|
|
165
|
+
const MD_STREAM_MIN_DELTA_CHARS = 40;
|
|
166
|
+
|
|
164
167
|
function MdNode(p) {
|
|
165
168
|
const refSink = (el) => {
|
|
166
169
|
if (!el) return;
|
|
@@ -169,7 +172,27 @@ function MdNode(p) {
|
|
|
169
172
|
// once the loader recovers, instead of staying plain-escaped forever.
|
|
170
173
|
const srcKey = (isMarkdownDegraded() ? '~degraded~' : '') + (p.text || '');
|
|
171
174
|
if (el.dataset.mdSrc === srcKey) return;
|
|
175
|
+
// While streaming (text still growing, not the final settle), a full
|
|
176
|
+
// re-parse of the WHOLE accumulated text on every rAF tick is the
|
|
177
|
+
// dominant cost of a long stream. Throttle: skip the parse unless
|
|
178
|
+
// enough time or enough new characters landed since the last one.
|
|
179
|
+
// p.streamingCaret (already threaded by the host for the stream-head
|
|
180
|
+
// caret) marks "still streaming"; its absence forces the final parse
|
|
181
|
+
// so nothing is left un-parsed once the turn settles.
|
|
182
|
+
const parsedLen = el.dataset.mdParsedLen ? Number(el.dataset.mdParsedLen) : 0;
|
|
183
|
+
const lastParseAt = el.dataset.mdLastParseAt ? Number(el.dataset.mdLastParseAt) : 0;
|
|
184
|
+
const now = (typeof performance !== 'undefined' ? performance.now() : Date.now());
|
|
185
|
+
if (p.streamingCaret && parsedLen > 0 &&
|
|
186
|
+
(now - lastParseAt) < MD_STREAM_THROTTLE_MS &&
|
|
187
|
+
(srcKey.length - parsedLen) < MD_STREAM_MIN_DELTA_CHARS) {
|
|
188
|
+
// Not enough new content/time yet — paint raw text so the latest
|
|
189
|
+
// characters are visible, but defer the expensive re-parse.
|
|
190
|
+
el.textContent = p.text || '';
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
172
193
|
el.dataset.mdSrc = srcKey;
|
|
194
|
+
el.dataset.mdParsedLen = String(srcKey.length);
|
|
195
|
+
el.dataset.mdLastParseAt = String(now);
|
|
173
196
|
// Markdown stack still loading (or down): paint the raw text
|
|
174
197
|
// synchronously so streamed tokens are visible the same frame they
|
|
175
198
|
// arrive (an empty bubble until the CDN import resolves reads as a
|
|
@@ -215,8 +238,20 @@ function CodeNode(p) {
|
|
|
215
238
|
// surrounding ChatMessage chrome (avatar/meta/reactions) stays consistent.
|
|
216
239
|
function ToolCallNode(p) {
|
|
217
240
|
const status = p.status || (p.error ? 'error' : (p.result != null ? 'done' : 'running'));
|
|
218
|
-
|
|
219
|
-
|
|
241
|
+
// Args/result are re-stringified on every rAF re-render while any part of
|
|
242
|
+
// the turn is streaming, even for collapsed cards whose own args/result
|
|
243
|
+
// haven't changed since the last frame. Cache by identity on the part
|
|
244
|
+
// object itself so an unchanged args/result skips the stringify.
|
|
245
|
+
if (p._argsCache !== p.args) {
|
|
246
|
+
p._argsTextCache = typeof p.args === 'string' ? p.args : JSON.stringify(p.args || {}, null, 2);
|
|
247
|
+
p._argsCache = p.args;
|
|
248
|
+
}
|
|
249
|
+
const argsText = p._argsTextCache;
|
|
250
|
+
if (p._resultCache !== p.result) {
|
|
251
|
+
p._resultTextCache = p.result == null ? '' : (typeof p.result === 'string' ? p.result : JSON.stringify(p.result, null, 2));
|
|
252
|
+
p._resultCache = p.result;
|
|
253
|
+
}
|
|
254
|
+
const resultText = p._resultTextCache;
|
|
220
255
|
const hasArgs = p.args != null && argsText !== '{}' && argsText.trim() !== '';
|
|
221
256
|
// Default-open while running or on error so the user sees live progress / failure detail;
|
|
222
257
|
// collapse on success unless the caller explicitly overrides with open:true.
|
package/src/components/shell.js
CHANGED
|
@@ -214,7 +214,14 @@ export function Topbar({ brand = '247420', leaf = '', items = [], active = '', o
|
|
|
214
214
|
Brand({ name: brand, leaf }),
|
|
215
215
|
search ? h('label', { class: 'app-search' },
|
|
216
216
|
h('span', { class: 'icon', 'aria-hidden': 'true' }, 'search'),
|
|
217
|
-
|
|
217
|
+
// `search` is either a plain placeholder string (renders the
|
|
218
|
+
// default uncontrolled input) or a caller-built VElement (has
|
|
219
|
+
// .type/.props — e.g. a controlled <input> wired to app state)
|
|
220
|
+
// rendered as-is. Stringifying a VElement into placeholder/
|
|
221
|
+
// aria-label previously produced literal "[object Object]" text.
|
|
222
|
+
(search && typeof search === 'object' && 'type' in search)
|
|
223
|
+
? search
|
|
224
|
+
: h('input', { type: 'search', name: 'q', placeholder: search, 'aria-label': `search ${search}` })
|
|
218
225
|
) : null,
|
|
219
226
|
h('nav', { 'aria-label': 'main navigation' }, ...items.map(([label, href]) => {
|
|
220
227
|
const cleanLabel = String(label).replace(' ->', '');
|