@promptbook/components 0.102.0-4 → 0.102.0-5
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/esm/index.es.js +82 -41
- package/esm/index.es.js.map +1 -1
- package/esm/typings/src/book-components/BookEditor/utils.d.ts +8 -0
- package/esm/typings/src/llm-providers/openai/OpenAiCompatibleExecutionTools.d.ts +1 -1
- package/esm/typings/src/types/Prompt.d.ts +5 -0
- package/esm/typings/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +82 -41
- package/umd/index.umd.js.map +1 -1
package/esm/index.es.js
CHANGED
|
@@ -21,7 +21,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
|
|
|
21
21
|
* @generated
|
|
22
22
|
* @see https://github.com/webgptorg/promptbook
|
|
23
23
|
*/
|
|
24
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.102.0-
|
|
24
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.102.0-5';
|
|
25
25
|
/**
|
|
26
26
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
27
27
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3161,6 +3161,23 @@ const DEFAULT_BOOK_FONT_CLASS = styles.bookEditorSerif;
|
|
|
3161
3161
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3162
3162
|
*/
|
|
3163
3163
|
|
|
3164
|
+
// Debounce utility for BookEditor and related components
|
|
3165
|
+
// [🧠] Use this for debouncing highlight and other expensive operations
|
|
3166
|
+
/**
|
|
3167
|
+
* @private
|
|
3168
|
+
*/
|
|
3169
|
+
function debounce(fn, delay) {
|
|
3170
|
+
let timeout = null;
|
|
3171
|
+
return (...args) => {
|
|
3172
|
+
if (timeout)
|
|
3173
|
+
clearTimeout(timeout);
|
|
3174
|
+
timeout = setTimeout(() => fn(...args), delay);
|
|
3175
|
+
};
|
|
3176
|
+
}
|
|
3177
|
+
/**
|
|
3178
|
+
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3179
|
+
* TODO: !!! remove this file */
|
|
3180
|
+
|
|
3164
3181
|
/**
|
|
3165
3182
|
* @private util of `<BookEditor />`
|
|
3166
3183
|
*/
|
|
@@ -3173,6 +3190,33 @@ function BookEditorInner(props) {
|
|
|
3173
3190
|
const highlightRef = useRef(null);
|
|
3174
3191
|
const [lineHeight, setLineHeight] = useState(32);
|
|
3175
3192
|
const [isDragOver, setIsDragOver] = useState(false);
|
|
3193
|
+
// Virtualization state: visible line range
|
|
3194
|
+
const [visibleRange, setVisibleRange] = useState([0, 30]);
|
|
3195
|
+
// Debounced update for visible range
|
|
3196
|
+
const updateVisibleRange = useCallback(debounce(() => {
|
|
3197
|
+
const textarea = textareaRef.current;
|
|
3198
|
+
if (!textarea)
|
|
3199
|
+
return;
|
|
3200
|
+
const scrollTop = textarea.scrollTop;
|
|
3201
|
+
const clientHeight = textarea.clientHeight;
|
|
3202
|
+
const totalLines = (value !== null && value !== void 0 ? value : '').split('\n').length;
|
|
3203
|
+
const firstLine = Math.max(0, Math.floor(scrollTop / lineHeight) - 10); // buffer
|
|
3204
|
+
const lastLine = Math.min(totalLines, Math.ceil((scrollTop + clientHeight) / lineHeight) + 10);
|
|
3205
|
+
setVisibleRange([firstLine, lastLine]);
|
|
3206
|
+
}, 30), [value, lineHeight]);
|
|
3207
|
+
// Update visible range on scroll/resize/value change
|
|
3208
|
+
useEffect(() => {
|
|
3209
|
+
updateVisibleRange();
|
|
3210
|
+
const textarea = textareaRef.current;
|
|
3211
|
+
if (!textarea)
|
|
3212
|
+
return;
|
|
3213
|
+
textarea.addEventListener('scroll', updateVisibleRange);
|
|
3214
|
+
window.addEventListener('resize', updateVisibleRange);
|
|
3215
|
+
return () => {
|
|
3216
|
+
textarea.removeEventListener('scroll', updateVisibleRange);
|
|
3217
|
+
window.removeEventListener('resize', updateVisibleRange);
|
|
3218
|
+
};
|
|
3219
|
+
}, [updateVisibleRange]);
|
|
3176
3220
|
const handleChange = useCallback((event) => {
|
|
3177
3221
|
const newValue = event.target.value;
|
|
3178
3222
|
if (controlledValue !== undefined) {
|
|
@@ -3485,29 +3529,32 @@ function BookEditorInner(props) {
|
|
|
3485
3529
|
});
|
|
3486
3530
|
return parameters.sort((a, b) => a.start - b.start);
|
|
3487
3531
|
}, [atParameterRegex, braceParameterRegex]);
|
|
3532
|
+
// Virtualized, debounced highlight rendering for large books
|
|
3488
3533
|
const highlightedHtml = useMemo(() => {
|
|
3489
3534
|
const text = value !== null && value !== void 0 ? value : '';
|
|
3490
|
-
|
|
3535
|
+
const lines = text.split('\n');
|
|
3536
|
+
const [firstLine, lastLine] = visibleRange;
|
|
3537
|
+
const visibleLines = lines.slice(firstLine, lastLine);
|
|
3538
|
+
// Compute offset for correct line numbers
|
|
3539
|
+
const offset = lines.slice(0, firstLine).join('\n').length + (firstLine > 0 ? 1 : 0);
|
|
3491
3540
|
let out = '';
|
|
3492
3541
|
const processedRanges = [];
|
|
3493
|
-
//
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3542
|
+
// Highlighting logic for visible lines only
|
|
3543
|
+
const visibleText = visibleLines.join('\n');
|
|
3544
|
+
// First, handle comment-like commitments (NOTE, COMMENT, NONCE)
|
|
3545
|
+
visibleText.replace(commentRegex, (match, ...args) => {
|
|
3546
|
+
const index = args[args.length - 2] + offset;
|
|
3498
3547
|
const adjustedStart = match.startsWith('\n') ? index + 1 : index;
|
|
3499
3548
|
const adjustedMatch = match.startsWith('\n') ? match.slice(1) : match;
|
|
3500
3549
|
processedRanges.push({ start: adjustedStart, end: adjustedStart + adjustedMatch.length, type: 'comment' });
|
|
3501
3550
|
return match;
|
|
3502
3551
|
});
|
|
3503
|
-
//
|
|
3504
|
-
|
|
3505
|
-
const index = args[args.length - 2];
|
|
3506
|
-
// Adjust index to skip the newline character if present at the beginning of match
|
|
3552
|
+
// META commitments
|
|
3553
|
+
visibleText.replace(metaRegex, (match, ...args) => {
|
|
3554
|
+
const index = args[args.length - 2] + offset;
|
|
3507
3555
|
const adjustedStart = match.startsWith('\n') ? index + 1 : index;
|
|
3508
3556
|
const adjustedMatch = match.startsWith('\n') ? match.slice(1) : match;
|
|
3509
3557
|
const matchEnd = adjustedStart + adjustedMatch.length;
|
|
3510
|
-
// Check if this match overlaps with any existing range (especially comments)
|
|
3511
3558
|
const overlaps = processedRanges.some((range) => (adjustedStart >= range.start && adjustedStart < range.end) ||
|
|
3512
3559
|
(matchEnd > range.start && matchEnd <= range.end) ||
|
|
3513
3560
|
(adjustedStart < range.start && matchEnd > range.end));
|
|
@@ -3516,14 +3563,12 @@ function BookEditorInner(props) {
|
|
|
3516
3563
|
}
|
|
3517
3564
|
return match;
|
|
3518
3565
|
});
|
|
3519
|
-
//
|
|
3520
|
-
|
|
3521
|
-
const index = args[args.length - 2];
|
|
3522
|
-
// Adjust index to skip the newline character if present at the beginning of match
|
|
3566
|
+
// Regular commitment types
|
|
3567
|
+
visibleText.replace(typeRegex, (match, ...args) => {
|
|
3568
|
+
const index = args[args.length - 2] + offset;
|
|
3523
3569
|
const adjustedStart = match.startsWith('\n') ? index + 1 : index;
|
|
3524
3570
|
const adjustedMatch = match.startsWith('\n') ? match.slice(1) : match;
|
|
3525
3571
|
const matchEnd = adjustedStart + adjustedMatch.length;
|
|
3526
|
-
// Check if this match overlaps with any existing range
|
|
3527
3572
|
const overlaps = processedRanges.some((range) => (adjustedStart >= range.start && adjustedStart < range.end) ||
|
|
3528
3573
|
(matchEnd > range.start && matchEnd <= range.end) ||
|
|
3529
3574
|
(adjustedStart < range.start && matchEnd > range.end));
|
|
@@ -3532,29 +3577,28 @@ function BookEditorInner(props) {
|
|
|
3532
3577
|
}
|
|
3533
3578
|
return match;
|
|
3534
3579
|
});
|
|
3535
|
-
//
|
|
3536
|
-
|
|
3537
|
-
const unifiedParameters = extractUnifiedParameters(text);
|
|
3580
|
+
// Parameters
|
|
3581
|
+
const unifiedParameters = extractUnifiedParameters(visibleText);
|
|
3538
3582
|
unifiedParameters.forEach((param) => {
|
|
3539
|
-
|
|
3540
|
-
const
|
|
3541
|
-
|
|
3542
|
-
(
|
|
3583
|
+
const paramStart = param.start + offset;
|
|
3584
|
+
const paramEnd = param.end + offset;
|
|
3585
|
+
const overlaps = processedRanges.some((range) => (paramStart >= range.start && paramStart < range.end) ||
|
|
3586
|
+
(paramEnd > range.start && paramEnd <= range.end) ||
|
|
3587
|
+
(paramStart < range.start && paramEnd > range.end));
|
|
3543
3588
|
if (!overlaps) {
|
|
3544
3589
|
processedRanges.push({
|
|
3545
|
-
start:
|
|
3546
|
-
end:
|
|
3590
|
+
start: paramStart,
|
|
3591
|
+
end: paramEnd,
|
|
3547
3592
|
type: 'parameter',
|
|
3548
3593
|
});
|
|
3549
3594
|
}
|
|
3550
3595
|
});
|
|
3551
3596
|
// Sort ranges by start position
|
|
3552
3597
|
processedRanges.sort((a, b) => a.start - b.start);
|
|
3553
|
-
// Build the highlighted HTML
|
|
3598
|
+
// Build the highlighted HTML for the visible lines only
|
|
3599
|
+
let visibleLastIndex = offset;
|
|
3554
3600
|
processedRanges.forEach((range) => {
|
|
3555
|
-
|
|
3556
|
-
out += escapeHtml(text.slice(lastIndex, range.start));
|
|
3557
|
-
// Add highlighted text with appropriate class
|
|
3601
|
+
out += escapeHtml(text.slice(visibleLastIndex, range.start));
|
|
3558
3602
|
const matchText = text.slice(range.start, range.end);
|
|
3559
3603
|
let cssClass;
|
|
3560
3604
|
switch (range.type) {
|
|
@@ -3562,11 +3606,9 @@ function BookEditorInner(props) {
|
|
|
3562
3606
|
cssClass = 'book-highlight-keyword';
|
|
3563
3607
|
break;
|
|
3564
3608
|
case 'parameter':
|
|
3565
|
-
// Use the unified parameter class, but maintain backward compatibility
|
|
3566
3609
|
cssClass = 'book-highlight-parameter';
|
|
3567
3610
|
break;
|
|
3568
3611
|
case 'comment':
|
|
3569
|
-
// NOTE, COMMENT, NONCE commitments should be highlighted as gray comments
|
|
3570
3612
|
cssClass = 'book-highlight-comment';
|
|
3571
3613
|
break;
|
|
3572
3614
|
default:
|
|
@@ -3574,16 +3616,15 @@ function BookEditorInner(props) {
|
|
|
3574
3616
|
break;
|
|
3575
3617
|
}
|
|
3576
3618
|
out += `<span class="${cssClass}">${escapeHtml(matchText)}</span>`;
|
|
3577
|
-
|
|
3619
|
+
visibleLastIndex = range.end;
|
|
3578
3620
|
});
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
}, [value, typeRegex, metaRegex, extractUnifiedParameters]);
|
|
3621
|
+
out += escapeHtml(text.slice(visibleLastIndex, offset + visibleText.length));
|
|
3622
|
+
const resultLines = out.split('\n').slice(firstLine, lastLine);
|
|
3623
|
+
if (resultLines.length > 0 && firstLine === 0) {
|
|
3624
|
+
resultLines[0] = `<span class="book-highlight-title">${resultLines[0]}</span>`;
|
|
3625
|
+
}
|
|
3626
|
+
return resultLines.join('\n');
|
|
3627
|
+
}, [value, typeRegex, metaRegex, extractUnifiedParameters, visibleRange]);
|
|
3587
3628
|
return (jsx("div", { className: classNames(styles.bookEditorContainer, isVerbose && styles.isVerbose, className), children: jsxs("div", { className: classNames(styles.bookEditorWrapper, effectiveFontClassName, isBorderRadiusDisabled && styles.isBorderRadiusDisabled), children: [jsx("div", { "aria-hidden": true, className: styles.bookEditorBackground, style: { backgroundImage: 'none' } }), jsx("pre", { ref: highlightRef, "aria-hidden": true, className: `${styles.bookEditorHighlight} ${effectiveFontClassName}`, style: {
|
|
3588
3629
|
lineHeight: `${lineHeight}px`,
|
|
3589
3630
|
backgroundImage: `linear-gradient(90deg, transparent 30px, rgba(59,130,246,0.3) 30px, rgba(59,130,246,0.3) 31px, transparent 31px), repeating-linear-gradient(0deg, transparent, transparent calc(${lineHeight}px - 1px), rgba(0,0,0,0.06) ${lineHeight}px)`,
|