anentrypoint-design 0.0.330 → 0.0.331
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/dist/247420.js +9 -9
- package/package.json +1 -1
- package/src/components/chat-message-parts.js +37 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.331",
|
|
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",
|
|
@@ -130,6 +130,15 @@ export function injectCodeCopy(container) {
|
|
|
130
130
|
const MD_STREAM_THROTTLE_MS = 120;
|
|
131
131
|
const MD_STREAM_MIN_DELTA_CHARS = 40;
|
|
132
132
|
|
|
133
|
+
// requestIdleCallback with a setTimeout fallback (Safari/non-browser test
|
|
134
|
+
// contexts lack the real API). A settled historical message's parse is not
|
|
135
|
+
// latency-critical the way a streaming turn's is — deferring it off the
|
|
136
|
+
// critical path keeps a session-load burst of N historical bubbles from
|
|
137
|
+
// racing N synchronous parses on the same tick.
|
|
138
|
+
const scheduleIdle = typeof requestIdleCallback === 'function'
|
|
139
|
+
? (fn) => requestIdleCallback(fn, { timeout: 500 })
|
|
140
|
+
: (fn) => setTimeout(fn, 0);
|
|
141
|
+
|
|
133
142
|
function MdNode(p) {
|
|
134
143
|
const refSink = (el) => {
|
|
135
144
|
if (!el) return;
|
|
@@ -164,19 +173,34 @@ function MdNode(p) {
|
|
|
164
173
|
// arrive (an empty bubble until the CDN import resolves reads as a
|
|
165
174
|
// hang); the resolved render swaps in sanitized markdown in place.
|
|
166
175
|
if (isMarkdownDegraded()) el.textContent = p.text || '';
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
function doParse() {
|
|
177
|
+
renderMarkdownCached(p.text || '').then((html) => {
|
|
178
|
+
// The element may have been recycled (webjsx applyDiff reused this
|
|
179
|
+
// DOM node for a different message) or detached by the time an
|
|
180
|
+
// idle-deferred parse resolves -- re-check the source key still
|
|
181
|
+
// matches before swapping innerHTML into what could now be a
|
|
182
|
+
// completely different message's bubble.
|
|
183
|
+
if (el.dataset.mdSrc !== srcKey) return;
|
|
184
|
+
const swap = () => { el.innerHTML = html; injectCodeCopy(el); };
|
|
185
|
+
// Don't blow away an active text selection inside this bubble mid-swap
|
|
186
|
+
// (e.g. the user is mid-copy while a stream tick settles). Defer the
|
|
187
|
+
// swap once, until the selection changes (cleared or moved elsewhere).
|
|
188
|
+
const sel = typeof window !== 'undefined' ? window.getSelection() : null;
|
|
189
|
+
if (sel && sel.anchorNode && el.contains(sel.anchorNode)) {
|
|
190
|
+
const onSelChange = () => { document.removeEventListener('selectionchange', onSelChange); swap(); };
|
|
191
|
+
document.addEventListener('selectionchange', onSelChange, { once: true });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
swap();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Streaming turns parse immediately (latency-critical: the user is
|
|
198
|
+
// watching this bubble grow). A settled historical message (no
|
|
199
|
+
// streamingCaret) is deferred to an idle slot -- not on the critical
|
|
200
|
+
// render path, so a page mounting many historical bubbles at once
|
|
201
|
+
// (session load) doesn't burst-parse them all synchronously.
|
|
202
|
+
if (p.streamingCaret) doParse();
|
|
203
|
+
else scheduleIdle(doParse);
|
|
180
204
|
};
|
|
181
205
|
return h('div', { class: 'chat-bubble chat-md', ref: refSink });
|
|
182
206
|
}
|