@promptbook/components 0.100.0-41 → 0.100.0-43

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
2
+ import { useMemo, useState, useRef, useCallback, useEffect } from 'react';
3
+ import spaceTrim$1, { spaceTrim } from 'spacetrim';
3
4
  import { createPortal } from 'react-dom';
4
- import spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
5
5
 
6
6
  // ⚠️ WARNING: This code has been generated so that any manual changes will be overwritten
7
7
  /**
@@ -17,7 +17,7 @@ const BOOK_LANGUAGE_VERSION = '1.0.0';
17
17
  * @generated
18
18
  * @see https://github.com/webgptorg/promptbook
19
19
  */
20
- const PROMPTBOOK_ENGINE_VERSION = '0.100.0-41';
20
+ const PROMPTBOOK_ENGINE_VERSION = '0.100.0-43';
21
21
  /**
22
22
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
23
23
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -75,37 +75,35 @@ function AvatarChip(props) {
75
75
  }
76
76
 
77
77
  /**
78
- * Type guard to check if a string is a valid agent source
78
+ * Extracts profile image URL from agent definition text and returns cleaned system message
79
+ * @param systemMessage The original system message that may contain META IMAGE line
80
+ * @returns Object with profileImageUrl (if found) and cleanedSystemMessage (without META IMAGE line)
79
81
  *
80
- * @public exported from `@promptbook/core`
82
+ * @private - TODO: [🧠] Maybe should be public?
81
83
  */
82
- function isValidBook(value) {
83
- // Basic validation - agent source should have at least a name (first line)
84
- return typeof value === 'string' /* && value.trim().length > 0 */;
85
- }
86
84
  /**
87
- * Validates and converts a string to agent source branded type
88
- * This function should be used when you have a string that you know represents agent source
89
- * but need to convert it to the branded type for type safety
85
+ * Generates a gravatar URL based on agent name for fallback avatar
86
+ * @param name The agent name to generate avatar for
87
+ * @returns Gravatar URL
90
88
  *
91
- * @public exported from `@promptbook/core`
89
+ * @private - TODO: [🧠] Maybe should be public?
92
90
  */
93
- function validateBook(source) {
94
- if (!isValidBook(source)) {
95
- throw new Error('Invalid agent source: must be a string');
96
- }
97
- return source;
91
+ function generateGravatarUrl(name) {
92
+ // Use a default name if none provided
93
+ const safeName = name || 'Anonymous Agent';
94
+ // Create a simple hash from the name for consistent avatar
95
+ let hash = 0;
96
+ for (let i = 0; i < safeName.length; i++) {
97
+ const char = safeName.charCodeAt(i);
98
+ hash = (hash << 5) - hash + char;
99
+ hash = hash & hash; // Convert to 32bit integer
100
+ }
101
+ const avatarId = Math.abs(hash).toString();
102
+ return `https://www.gravatar.com/avatar/${avatarId}?default=robohash&size=200&rating=x`;
98
103
  }
99
104
  /**
100
- * Default book
101
- *
102
- * @public exported from `@promptbook/core`
105
+ * Note: [💞] Ignore a discrepancy between file name and entity name
103
106
  */
104
- const DEFAULT_BOOK = validateBook(spaceTrim(`
105
- AI Avatar
106
-
107
- PERSONA A friendly AI assistant that helps you with your tasks
108
- `));
109
107
 
110
108
  /**
111
109
  * Freezes the given object and all its nested objects recursively
@@ -260,7 +258,7 @@ class ActionCommitmentDefinition extends BaseCommitmentDefinition {
260
258
  * Markdown documentation for ACTION commitment.
261
259
  */
262
260
  get documentation() {
263
- return spaceTrim$1(`
261
+ return spaceTrim(`
264
262
  # ACTION
265
263
 
266
264
  Defines specific actions or capabilities that the agent can perform.
@@ -343,7 +341,7 @@ class FormatCommitmentDefinition extends BaseCommitmentDefinition {
343
341
  * Markdown documentation for FORMAT commitment.
344
342
  */
345
343
  get documentation() {
346
- return spaceTrim$1(`
344
+ return spaceTrim(`
347
345
  # FORMAT
348
346
 
349
347
  Defines the specific output structure and formatting for responses (data formats, templates, structure).
@@ -465,7 +463,7 @@ let DEFAULT_IS_VERBOSE = false;
465
463
  function getErrorReportUrl(error) {
466
464
  const report = {
467
465
  title: `🐜 Error report from ${NAME}`,
468
- body: spaceTrim((block) => `
466
+ body: spaceTrim$1((block) => `
469
467
 
470
468
 
471
469
  \`${error.name || 'Error'}\` has occurred in the [${NAME}], please look into it @${ADMIN_GITHUB_NAME}.
@@ -508,7 +506,7 @@ function getErrorReportUrl(error) {
508
506
  */
509
507
  class UnexpectedError extends Error {
510
508
  constructor(message) {
511
- super(spaceTrim$1((block) => `
509
+ super(spaceTrim((block) => `
512
510
  ${block(message)}
513
511
 
514
512
  Note: This error should not happen.
@@ -534,7 +532,7 @@ class WrappedError extends Error {
534
532
  constructor(whatWasThrown) {
535
533
  const tag = `[🤮]`;
536
534
  console.error(tag, whatWasThrown);
537
- super(spaceTrim$1(`
535
+ super(spaceTrim(`
538
536
  Non-Error object was thrown
539
537
 
540
538
  Note: Look for ${tag} in the console for more details
@@ -591,7 +589,7 @@ const promptbookFetch = async (urlOrRequest, init) => {
591
589
  else if (urlOrRequest instanceof Request) {
592
590
  url = urlOrRequest.url;
593
591
  }
594
- throw new PromptbookFetchError(spaceTrim((block) => `
592
+ throw new PromptbookFetchError(spaceTrim$1((block) => `
595
593
  Can not fetch "${url}"
596
594
 
597
595
  Fetch error:
@@ -836,7 +834,7 @@ class KnowledgeCommitmentDefinition extends BaseCommitmentDefinition {
836
834
  * Markdown documentation for KNOWLEDGE commitment.
837
835
  */
838
836
  get documentation() {
839
- return spaceTrim$1(`
837
+ return spaceTrim(`
840
838
  # KNOWLEDGE
841
839
 
842
840
  Adds specific knowledge, facts, or context to the agent using a RAG (Retrieval-Augmented Generation) approach for external sources.
@@ -965,7 +963,7 @@ class MetaImageCommitmentDefinition extends BaseCommitmentDefinition {
965
963
  * Markdown documentation for META IMAGE commitment.
966
964
  */
967
965
  get documentation() {
968
- return spaceTrim$1(`
966
+ return spaceTrim(`
969
967
  # META IMAGE
970
968
 
971
969
  Sets the agent's avatar/profile image URL.
@@ -1060,7 +1058,7 @@ class MetaLinkCommitmentDefinition extends BaseCommitmentDefinition {
1060
1058
  * Markdown documentation for META LINK commitment.
1061
1059
  */
1062
1060
  get documentation() {
1063
- return spaceTrim$1(`
1061
+ return spaceTrim(`
1064
1062
  # META LINK
1065
1063
 
1066
1064
  Represents a profile or source link for the person the agent is modeled after.
@@ -1161,7 +1159,7 @@ class ModelCommitmentDefinition extends BaseCommitmentDefinition {
1161
1159
  * Markdown documentation for MODEL commitment.
1162
1160
  */
1163
1161
  get documentation() {
1164
- return spaceTrim$1(`
1162
+ return spaceTrim(`
1165
1163
  # MODEL
1166
1164
 
1167
1165
  Specifies which AI model to use and optional decoding parameters.
@@ -1293,7 +1291,7 @@ class NoteCommitmentDefinition extends BaseCommitmentDefinition {
1293
1291
  * Markdown documentation for NOTE commitment.
1294
1292
  */
1295
1293
  get documentation() {
1296
- return spaceTrim$1(`
1294
+ return spaceTrim(`
1297
1295
  # NOTE
1298
1296
 
1299
1297
  Adds comments for documentation without changing agent behavior.
@@ -1400,7 +1398,7 @@ class PersonaCommitmentDefinition extends BaseCommitmentDefinition {
1400
1398
  * Markdown documentation for PERSONA commitment.
1401
1399
  */
1402
1400
  get documentation() {
1403
- return spaceTrim$1(`
1401
+ return spaceTrim(`
1404
1402
  # PERSONA
1405
1403
 
1406
1404
  Defines who the agent is, their background, expertise, and personality traits.
@@ -1531,7 +1529,7 @@ class RuleCommitmentDefinition extends BaseCommitmentDefinition {
1531
1529
  * Markdown documentation for RULE/RULES commitment.
1532
1530
  */
1533
1531
  get documentation() {
1534
- return spaceTrim$1(`
1532
+ return spaceTrim(`
1535
1533
  # ${this.type}
1536
1534
 
1537
1535
  Adds behavioral constraints and guidelines that the agent must follow.
@@ -1620,7 +1618,7 @@ class SampleCommitmentDefinition extends BaseCommitmentDefinition {
1620
1618
  * Markdown documentation for SAMPLE/EXAMPLE commitment.
1621
1619
  */
1622
1620
  get documentation() {
1623
- return spaceTrim$1(`
1621
+ return spaceTrim(`
1624
1622
  # ${this.type}
1625
1623
 
1626
1624
  Provides examples of how the agent should respond or behave in certain situations.
@@ -1708,7 +1706,7 @@ class StyleCommitmentDefinition extends BaseCommitmentDefinition {
1708
1706
  * Markdown documentation for STYLE commitment.
1709
1707
  */
1710
1708
  get documentation() {
1711
- return spaceTrim$1(`
1709
+ return spaceTrim(`
1712
1710
  # STYLE
1713
1711
 
1714
1712
  Defines how the agent should format and present its responses (tone, writing style, formatting).
@@ -1783,7 +1781,7 @@ class NotYetImplementedCommitmentDefinition extends BaseCommitmentDefinition {
1783
1781
  * Markdown documentation available at runtime.
1784
1782
  */
1785
1783
  get documentation() {
1786
- return spaceTrim$1(`
1784
+ return spaceTrim(`
1787
1785
  # ${this.type}
1788
1786
 
1789
1787
  This commitment is not yet fully implemented.
@@ -1871,6 +1869,199 @@ function getAllCommitmentDefinitions() {
1871
1869
  * Note: [💞] Ignore a discrepancy between file name and entity name
1872
1870
  */
1873
1871
 
1872
+ /**
1873
+ * Parses agent source using the new commitment system with multiline support
1874
+ * This function replaces the hardcoded commitment parsing in the original parseAgentSource
1875
+ *
1876
+ * @private
1877
+ */
1878
+ function parseAgentSourceWithCommitments(agentSource) {
1879
+ var _a, _b, _c;
1880
+ if (!agentSource || !agentSource.trim()) {
1881
+ return {
1882
+ agentName: null,
1883
+ commitments: [],
1884
+ nonCommitmentLines: [],
1885
+ };
1886
+ }
1887
+ const lines = agentSource.split('\n');
1888
+ const agentName = (((_a = lines[0]) === null || _a === void 0 ? void 0 : _a.trim()) || null);
1889
+ const commitments = [];
1890
+ const nonCommitmentLines = [];
1891
+ // Always add the first line (agent name) to non-commitment lines
1892
+ if (lines[0] !== undefined) {
1893
+ nonCommitmentLines.push(lines[0]);
1894
+ }
1895
+ // Parse commitments with multiline support
1896
+ let currentCommitment = null;
1897
+ // Process lines starting from the second line (skip agent name)
1898
+ for (let i = 1; i < lines.length; i++) {
1899
+ const line = lines[i];
1900
+ if (line === undefined) {
1901
+ continue;
1902
+ }
1903
+ // Check if this line starts a new commitment
1904
+ let foundNewCommitment = false;
1905
+ for (const definition of COMMITMENT_REGISTRY) {
1906
+ const typeRegex = definition.createTypeRegex();
1907
+ const match = typeRegex.exec(line.trim());
1908
+ if (match && ((_b = match.groups) === null || _b === void 0 ? void 0 : _b.type)) {
1909
+ // Save the previous commitment if it exists
1910
+ if (currentCommitment) {
1911
+ const fullContent = currentCommitment.contentLines.join('\n');
1912
+ commitments.push({
1913
+ type: currentCommitment.type,
1914
+ content: spaceTrim(fullContent),
1915
+ originalLine: currentCommitment.originalStartLine,
1916
+ lineNumber: currentCommitment.startLineNumber,
1917
+ });
1918
+ }
1919
+ // Extract the initial content from the commitment line
1920
+ const fullRegex = definition.createRegex();
1921
+ const fullMatch = fullRegex.exec(line.trim());
1922
+ const initialContent = ((_c = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _c === void 0 ? void 0 : _c.contents) || '';
1923
+ // Start a new commitment
1924
+ currentCommitment = {
1925
+ type: definition.type,
1926
+ startLineNumber: i + 1,
1927
+ originalStartLine: line,
1928
+ contentLines: initialContent ? [initialContent] : [],
1929
+ };
1930
+ foundNewCommitment = true;
1931
+ break;
1932
+ }
1933
+ }
1934
+ if (!foundNewCommitment) {
1935
+ if (currentCommitment) {
1936
+ // This line belongs to the current commitment
1937
+ currentCommitment.contentLines.push(line);
1938
+ }
1939
+ else {
1940
+ // This line is not part of any commitment
1941
+ nonCommitmentLines.push(line);
1942
+ }
1943
+ }
1944
+ }
1945
+ // Don't forget to save the last commitment if it exists
1946
+ if (currentCommitment) {
1947
+ const fullContent = currentCommitment.contentLines.join('\n');
1948
+ commitments.push({
1949
+ type: currentCommitment.type,
1950
+ content: spaceTrim(fullContent),
1951
+ originalLine: currentCommitment.originalStartLine,
1952
+ lineNumber: currentCommitment.startLineNumber,
1953
+ });
1954
+ }
1955
+ return {
1956
+ agentName,
1957
+ commitments,
1958
+ nonCommitmentLines,
1959
+ };
1960
+ }
1961
+ /**
1962
+ * Extracts basic information from agent source using the new commitment system
1963
+ * This maintains compatibility with the original parseAgentSource interface
1964
+ *
1965
+ * @private
1966
+ */
1967
+ function parseAgentSourceBasicInfo(agentSource) {
1968
+ const parseResult = parseAgentSourceWithCommitments(agentSource);
1969
+ // Find PERSONA and META IMAGE commitments
1970
+ let personaDescription = null;
1971
+ let profileImageUrl;
1972
+ for (const commitment of parseResult.commitments) {
1973
+ if (commitment.type === 'PERSONA' && !personaDescription) {
1974
+ personaDescription = commitment.content;
1975
+ }
1976
+ else if (commitment.type === 'META IMAGE' && !profileImageUrl) {
1977
+ profileImageUrl = commitment.content;
1978
+ }
1979
+ }
1980
+ // Generate gravatar fallback if no profile image specified
1981
+ if (!profileImageUrl) {
1982
+ profileImageUrl = generateGravatarUrl(parseResult.agentName);
1983
+ }
1984
+ return {
1985
+ agentName: parseResult.agentName,
1986
+ personaDescription,
1987
+ profileImageUrl,
1988
+ };
1989
+ }
1990
+
1991
+ /**
1992
+ * Parses agent source string into its components
1993
+ */
1994
+ // Cache for parsed agent sources to prevent repeated parsing
1995
+ const parsedAgentSourceCache = new Map();
1996
+ /**
1997
+ * Parses basic information from agent source
1998
+ *
1999
+ * There are 2 similar functions:
2000
+ * - `parseAgentSource` which is a lightweight parser for agent source, it parses basic information and its purpose is to be quick and synchronous. The commitments there are hardcoded.
2001
+ * - `createAgentModelRequirements` which is an asynchronous function that creates model requirements it applies each commitment one by one and works asynchronously.
2002
+ *
2003
+ * @public exported from `@promptbook/core`
2004
+ */
2005
+ function parseAgentSource(agentSource) {
2006
+ // Check if we already parsed this agent source
2007
+ if (parsedAgentSourceCache.has(agentSource)) {
2008
+ return parsedAgentSourceCache.get(agentSource);
2009
+ }
2010
+ // Use the new commitment-based parsing system
2011
+ const result = parseAgentSourceBasicInfo(agentSource);
2012
+ // Cache the result
2013
+ parsedAgentSourceCache.set(agentSource, result);
2014
+ return result;
2015
+ }
2016
+
2017
+ /**
2018
+ * Shows a chip with avatar's avatar and name based on the avatar source string
2019
+ *
2020
+ * This component is wrapped around the `<AvatarChip/>`, it just parses the avatar source string into `AvatarBasicInformation` and passes it to the `<AvatarChip/>` component.
2021
+ *
2022
+ * @public exported from `@promptbook/components`
2023
+ */
2024
+ function AvatarChipFromSource(props) {
2025
+ const { source } = props;
2026
+ const avatarBasicInformation = useMemo(() => {
2027
+ return parseAgentSource(source);
2028
+ }, [source]);
2029
+ return jsx(AvatarChip, { avatarBasicInformation: avatarBasicInformation, ...props });
2030
+ }
2031
+
2032
+ /**
2033
+ * Type guard to check if a string is a valid agent source
2034
+ *
2035
+ * @public exported from `@promptbook/core`
2036
+ */
2037
+ function isValidBook(value) {
2038
+ // Basic validation - agent source should have at least a name (first line)
2039
+ return typeof value === 'string' /* && value.trim().length > 0 */;
2040
+ }
2041
+ /**
2042
+ * Validates and converts a string to agent source branded type
2043
+ * This function should be used when you have a string that you know represents agent source
2044
+ * but need to convert it to the branded type for type safety
2045
+ *
2046
+ * @public exported from `@promptbook/core`
2047
+ */
2048
+ function validateBook(source) {
2049
+ if (!isValidBook(source)) {
2050
+ throw new Error('Invalid agent source: must be a string');
2051
+ }
2052
+ return source;
2053
+ }
2054
+ /**
2055
+ * Default book
2056
+ *
2057
+ * @public exported from `@promptbook/core`
2058
+ */
2059
+ const DEFAULT_BOOK = validateBook(spaceTrim$1(`
2060
+ AI Avatar
2061
+
2062
+ PERSONA A friendly AI assistant that helps you with your tasks
2063
+ `));
2064
+
1874
2065
  /**
1875
2066
  * Escape HTML to safely render user text inside a <pre> with dangerouslySetInnerHTML.
1876
2067
  *
@@ -1889,7 +2080,7 @@ function escapeRegex(input) {
1889
2080
  return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1890
2081
  }
1891
2082
 
1892
- var css_248z = ".BookEditor-module_bookEditorContainer__wLMwM{width:100%}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);overflow:hidden;position:relative;transition:box-shadow .2s ease-in-out}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_bookEditorWrapper__twppD:focus-within{box-shadow:0 0 0 3px rgba(99,102,241,.4);outline:2px solid transparent;outline-offset:2px}.BookEditor-module_bookEditorBackground__5O4wu,.BookEditor-module_bookEditorHighlight__vs37t{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.BookEditor-module_bookEditorHighlight__vs37t{-ms-overflow-style:none;color:#111827;font-size:1.125rem;overflow:auto;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:0;scrollbar-width:none;white-space:pre-wrap;z-index:10}.BookEditor-module_bookEditorHighlight__vs37t::-webkit-scrollbar{display:none}.BookEditor-module_bookEditorHighlight__vs37t .text-indigo-700{color:#4338ca}.BookEditor-module_bookEditorTextarea__mUURn{background-color:transparent;border:none;caret-color:#111827;color:transparent;font-size:1.125rem;height:28rem;outline:none;padding-left:46px;padding-right:46px;padding-top:15px;position:relative;resize:none;width:100%;z-index:20}.BookEditor-module_bookEditorTextarea__mUURn::selection{background-color:rgba(99,102,241,.6)}.BookEditor-module_bookEditorSerif__QRS7g{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.BookEditor-module_bookEditorVersion__fcjyB{background-color:rgba(99,102,241,.1);border-top:1px solid rgba(209,213,219,.8);color:rgba(17,24,39,.6);font-size:.875rem;padding:.5rem 1rem}.BookEditor-module_bookEditorVersion__fcjyB a{color:unset;text-decoration:none}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw4Q0FDSSxVQUNKLENBRUEsb0NBQ0ksMEJBQ0osQ0FFQSw0Q0FLSSxxQkFBdUIsQ0FEdkIscUNBQTBDLENBRDFDLGtCQUFtQixDQUduQixzQ0FBMkMsQ0FKM0MsZUFBZ0IsQ0FEaEIsaUJBQWtCLENBTWxCLHFDQUNKLENBRUEsa0RBQ0ksdUVBQ0osQ0FFQSx5REFHSSx3Q0FBNkMsQ0FGN0MsNkJBQThCLENBQzlCLGtCQUVKLENBV0EsNkZBSkksUUFBUyxDQUNULE1BQU8sQ0FMUCxtQkFBb0IsQ0FDcEIsaUJBQWtCLENBRWxCLE9BQVEsQ0FEUixLQXdCSixDQWxCQSw4Q0FpQkksdUJBQXdCLENBUnhCLGFBQXNCLENBQ3RCLGtCQUFtQixDQUpuQixhQUFjLENBU2Qsd0JBQXlCLENBSHpCLGlCQUFrQixDQUNsQixrQkFBbUIsQ0FGbkIsYUFBYyxDQUtkLG9CQUFxQixDQVJyQixvQkFBcUIsQ0FNckIsVUFJSixDQUVBLGlFQUNJLFlBQ0osQ0FFQSwrREFDSSxhQUNKLENBRUEsNkNBUUksNEJBQTZCLENBTTdCLFdBQVksQ0FSWixtQkFBNEIsQ0FENUIsaUJBQWtCLENBRWxCLGtCQUFtQixDQUhuQixZQUFhLENBS2IsWUFBYSxDQUdiLGlCQUFrQixDQUNsQixrQkFBbUIsQ0FGbkIsZ0JBQWlCLENBVmpCLGlCQUFrQixDQVNsQixXQUFZLENBUFosVUFBVyxDQURYLFVBYUosQ0FFQSx3REFDSSxvQ0FDSixDQUVBLDBDQUNJLGdFQUNKLENBRUEsNENBS0ksb0NBQXlDLENBRHpDLHlDQUE4QyxDQUY5Qyx1QkFBNEIsQ0FENUIsaUJBQW1CLENBRW5CLGtCQUdKLENBRUEsOENBQ0ksV0FBWSxDQUNaLG9CQUNKIiwiZmlsZSI6IkJvb2tFZGl0b3IubW9kdWxlLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5ib29rRWRpdG9yQ29udGFpbmVyIHtcbiAgICB3aWR0aDogMTAwJTtcbn1cblxuLmlzVmVyYm9zZSB7XG4gICAgb3V0bGluZTogMnB4IGRvdHRlZCByZ2IoMjU1IDExNyAzOCk7XG59XG5cbi5ib29rRWRpdG9yV3JhcHBlciB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgYm9yZGVyLXJhZGl1czogMXJlbTtcbiAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDIwOSwgMjEzLCAyMTksIDAuOCk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogd2hpdGU7XG4gICAgYm94LXNoYWRvdzogMCAxcHggMnB4IDAgcmdiYSgwLCAwLCAwLCAwLjA1KTtcbiAgICB0cmFuc2l0aW9uOiBib3gtc2hhZG93IDAuMnMgZWFzZS1pbi1vdXQ7XG59XG5cbi5ib29rRWRpdG9yV3JhcHBlcjpob3ZlciB7XG4gICAgYm94LXNoYWRvdzogMCA0cHggNnB4IC0xcHggcmdiYSgwLCAwLCAwLCAwLjEpLCAwIDJweCA0cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMDYpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6Zm9jdXMtd2l0aGluIHtcbiAgICBvdXRsaW5lOiAycHggc29saWQgdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZS1vZmZzZXQ6IDJweDtcbiAgICBib3gtc2hhZG93OiAwIDAgMCAzcHggcmdiYSg5OSwgMTAyLCAyNDEsIDAuNCk7XG59XG5cbi5ib29rRWRpdG9yQmFja2dyb3VuZCB7XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgIHRvcDogMDtcbiAgICByaWdodDogMDtcbiAgICBib3R0b206IDA7XG4gICAgbGVmdDogMDtcbn1cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQge1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGxlZnQ6IDA7XG4gICAgb3ZlcmZsb3c6IGF1dG87XG4gICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gICAgd2hpdGUtc3BhY2U6IHByZS13cmFwO1xuICAgIGNvbG9yOiByZ2IoMTcsIDI0LCAzOSk7XG4gICAgZm9udC1zaXplOiAxLjEyNXJlbTtcbiAgICBwYWRkaW5nLXRvcDogMDtcbiAgICBwYWRkaW5nLWxlZnQ6IDQ2cHg7XG4gICAgcGFkZGluZy1yaWdodDogNDZweDtcbiAgICB6LWluZGV4OiAxMDtcbiAgICBvdmVyZmxvdy13cmFwOiBicmVhay13b3JkO1xuICAgIHNjcm9sbGJhci13aWR0aDogbm9uZTtcbiAgICAtbXMtb3ZlcmZsb3ctc3R5bGU6IG5vbmU7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gICAgZGlzcGxheTogbm9uZTtcbn1cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQgOmdsb2JhbCgudGV4dC1pbmRpZ28tNzAwKSB7XG4gICAgY29sb3I6IHJnYig2NywgNTYsIDIwMik7XG59XG5cbi5ib29rRWRpdG9yVGV4dGFyZWEge1xuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICB6LWluZGV4OiAyMDtcbiAgICB3aWR0aDogMTAwJTtcbiAgICBoZWlnaHQ6IDI4cmVtO1xuICAgIGNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICBjYXJldC1jb2xvcjogcmdiKDE3LCAyNCwgMzkpO1xuICAgIGZvbnQtc2l6ZTogMS4xMjVyZW07XG4gICAgYmFja2dyb3VuZC1jb2xvcjogdHJhbnNwYXJlbnQ7XG4gICAgb3V0bGluZTogbm9uZTtcbiAgICByZXNpemU6IG5vbmU7XG4gICAgcGFkZGluZy10b3A6IDE1cHg7XG4gICAgcGFkZGluZy1sZWZ0OiA0NnB4O1xuICAgIHBhZGRpbmctcmlnaHQ6IDQ2cHg7XG4gICAgYm9yZGVyOiBub25lO1xufVxuXG4uYm9va0VkaXRvclRleHRhcmVhOjpzZWxlY3Rpb24ge1xuICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoOTksIDEwMiwgMjQxLCAwLjYpO1xufVxuXG4uYm9va0VkaXRvclNlcmlmIHtcbiAgICBmb250LWZhbWlseTogdWktc2VyaWYsIEdlb3JnaWEsIENhbWJyaWEsICdUaW1lcyBOZXcgUm9tYW4nLCBUaW1lcywgc2VyaWY7XG59XG5cbi5ib29rRWRpdG9yVmVyc2lvbiB7XG4gICAgZm9udC1zaXplOiAwLjg3NXJlbTtcbiAgICBjb2xvcjogcmdiYSgxNywgMjQsIDM5LCAwLjYpO1xuICAgIHBhZGRpbmc6IDAuNXJlbSAxcmVtO1xuICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCByZ2JhKDIwOSwgMjEzLCAyMTksIDAuOCk7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg5OSwgMTAyLCAyNDEsIDAuMSk7XG59XG5cbi5ib29rRWRpdG9yVmVyc2lvbiBhIHtcbiAgICBjb2xvcjogdW5zZXQ7XG4gICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xufVxuIl19 */";
2083
+ var css_248z = ".BookEditor-module_bookEditorContainer__wLMwM{width:100%}.BookEditor-module_isVerbose__VQ6iL{outline:2px dotted #ff7526}.BookEditor-module_bookEditorWrapper__twppD{background-color:#fff;border:1px solid rgba(209,213,219,.8);border-radius:1rem;box-shadow:0 1px 2px 0 rgba(0,0,0,.05);overflow:hidden;position:relative;transition:box-shadow .2s ease-in-out}.BookEditor-module_bookEditorWrapper__twppD:hover{box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)}.BookEditor-module_bookEditorWrapper__twppD:focus-within{box-shadow:0 0 0 3px rgba(99,102,241,.4);outline:2px solid transparent;outline-offset:2px}.BookEditor-module_bookEditorBackground__5O4wu,.BookEditor-module_bookEditorHighlight__vs37t{bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.BookEditor-module_bookEditorHighlight__vs37t{-ms-overflow-style:none;color:#111827;font-size:1.125rem;margin-bottom:50px;overflow:auto;overflow-wrap:break-word;padding-left:46px;padding-right:46px;padding-top:0;scrollbar-width:none;white-space:pre-wrap;z-index:10}.BookEditor-module_bookEditorHighlight__vs37t::-webkit-scrollbar{display:none}.BookEditor-module_bookEditorTextarea__mUURn{background-color:transparent;border:none;caret-color:#111827;color:transparent;font-size:1.125rem;height:28rem;outline:none;padding-left:46px;padding-right:46px;padding-top:15px;position:relative;resize:none;width:100%;z-index:20}.BookEditor-module_bookEditorTextarea__mUURn::selection{background-color:rgba(99,102,241,.6)}.BookEditor-module_bookEditorSerif__QRS7g{font-family:ui-serif,Georgia,Cambria,Times New Roman,Times,serif}.BookEditor-module_bookEditorVersion__fcjyB{background-color:rgba(99,102,241,.1);border-top:1px solid rgba(209,213,219,.8);color:rgba(17,24,39,.6);font-size:.875rem;padding:.5rem 1rem}.BookEditor-module_bookEditorVersion__fcjyB a{color:unset;text-decoration:none}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-title{color:#30a8bd;text-decoration:underline}.BookEditor-module_bookEditorHighlight__vs37t .book-highlight-keyword{color:#30a8bd}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkJvb2tFZGl0b3IubW9kdWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw4Q0FDSSxVQUNKLENBRUEsb0NBQ0ksMEJBQ0osQ0FFQSw0Q0FLSSxxQkFBdUIsQ0FEdkIscUNBQTBDLENBRDFDLGtCQUFtQixDQUduQixzQ0FBMkMsQ0FKM0MsZUFBZ0IsQ0FEaEIsaUJBQWtCLENBTWxCLHFDQUNKLENBRUEsa0RBQ0ksdUVBQ0osQ0FFQSx5REFHSSx3Q0FBNkMsQ0FGN0MsNkJBQThCLENBQzlCLGtCQUVKLENBV0EsNkZBSkksUUFBUyxDQUNULE1BQU8sQ0FMUCxtQkFBb0IsQ0FDcEIsaUJBQWtCLENBRWxCLE9BQVEsQ0FEUixLQXlCSixDQW5CQSw4Q0FrQkksdUJBQXdCLENBVHhCLGFBQXNCLENBQ3RCLGtCQUFtQixDQUluQixrQkFBbUIsQ0FSbkIsYUFBYyxDQVVkLHdCQUF5QixDQUp6QixpQkFBa0IsQ0FDbEIsa0JBQW1CLENBRm5CLGFBQWMsQ0FNZCxvQkFBcUIsQ0FUckIsb0JBQXFCLENBT3JCLFVBSUosQ0FFQSxpRUFDSSxZQUNKLENBRUEsNkNBUUksNEJBQTZCLENBTTdCLFdBQVksQ0FSWixtQkFBNEIsQ0FENUIsaUJBQWtCLENBRWxCLGtCQUFtQixDQUhuQixZQUFhLENBS2IsWUFBYSxDQUdiLGlCQUFrQixDQUNsQixrQkFBbUIsQ0FGbkIsZ0JBQWlCLENBVmpCLGlCQUFrQixDQVNsQixXQUFZLENBUFosVUFBVyxDQURYLFVBYUosQ0FFQSx3REFDSSxvQ0FDSixDQUVBLDBDQUNJLGdFQUNKLENBRUEsNENBS0ksb0NBQXlDLENBRHpDLHlDQUE4QyxDQUY5Qyx1QkFBNEIsQ0FENUIsaUJBQW1CLENBRW5CLGtCQUdKLENBRUEsOENBQ0ksV0FBWSxDQUNaLG9CQUNKLENBSUEsb0VBQ0ksYUFBYyxDQUNkLHlCQUNKLENBRUEsc0VBQ0ksYUFDSiIsImZpbGUiOiJCb29rRWRpdG9yLm1vZHVsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIuYm9va0VkaXRvckNvbnRhaW5lciB7XG4gICAgd2lkdGg6IDEwMCU7XG59XG5cbi5pc1ZlcmJvc2Uge1xuICAgIG91dGxpbmU6IDJweCBkb3R0ZWQgcmdiKDI1NSAxMTcgMzgpO1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXIge1xuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIGJvcmRlci1yYWRpdXM6IDFyZW07XG4gICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyMDksIDIxMywgMjE5LCAwLjgpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHdoaXRlO1xuICAgIGJveC1zaGFkb3c6IDAgMXB4IDJweCAwIHJnYmEoMCwgMCwgMCwgMC4wNSk7XG4gICAgdHJhbnNpdGlvbjogYm94LXNoYWRvdyAwLjJzIGVhc2UtaW4tb3V0O1xufVxuXG4uYm9va0VkaXRvcldyYXBwZXI6aG92ZXIge1xuICAgIGJveC1zaGFkb3c6IDAgNHB4IDZweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4xKSwgMCAycHggNHB4IC0xcHggcmdiYSgwLCAwLCAwLCAwLjA2KTtcbn1cblxuLmJvb2tFZGl0b3JXcmFwcGVyOmZvY3VzLXdpdGhpbiB7XG4gICAgb3V0bGluZTogMnB4IHNvbGlkIHRyYW5zcGFyZW50O1xuICAgIG91dGxpbmUtb2Zmc2V0OiAycHg7XG4gICAgYm94LXNoYWRvdzogMCAwIDAgM3B4IHJnYmEoOTksIDEwMiwgMjQxLCAwLjQpO1xufVxuXG4uYm9va0VkaXRvckJhY2tncm91bmQge1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDA7XG4gICAgcmlnaHQ6IDA7XG4gICAgYm90dG9tOiAwO1xuICAgIGxlZnQ6IDA7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0IHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgdG9wOiAwO1xuICAgIHJpZ2h0OiAwO1xuICAgIGJvdHRvbTogMDtcbiAgICBsZWZ0OiAwO1xuICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcbiAgICBjb2xvcjogcmdiKDE3LCAyNCwgMzkpO1xuICAgIGZvbnQtc2l6ZTogMS4xMjVyZW07XG4gICAgcGFkZGluZy10b3A6IDA7XG4gICAgcGFkZGluZy1sZWZ0OiA0NnB4O1xuICAgIHBhZGRpbmctcmlnaHQ6IDQ2cHg7XG4gICAgbWFyZ2luLWJvdHRvbTogNTBweDtcbiAgICB6LWluZGV4OiAxMDtcbiAgICBvdmVyZmxvdy13cmFwOiBicmVhay13b3JkO1xuICAgIHNjcm9sbGJhci13aWR0aDogbm9uZTtcbiAgICAtbXMtb3ZlcmZsb3ctc3R5bGU6IG5vbmU7XG59XG5cbi5ib29rRWRpdG9ySGlnaGxpZ2h0Ojotd2Via2l0LXNjcm9sbGJhciB7XG4gICAgZGlzcGxheTogbm9uZTtcbn1cblxuLmJvb2tFZGl0b3JUZXh0YXJlYSB7XG4gICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgIHotaW5kZXg6IDIwO1xuICAgIHdpZHRoOiAxMDAlO1xuICAgIGhlaWdodDogMjhyZW07XG4gICAgY29sb3I6IHRyYW5zcGFyZW50O1xuICAgIGNhcmV0LWNvbG9yOiByZ2IoMTcsIDI0LCAzOSk7XG4gICAgZm9udC1zaXplOiAxLjEyNXJlbTtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICBvdXRsaW5lOiBub25lO1xuICAgIHJlc2l6ZTogbm9uZTtcbiAgICBwYWRkaW5nLXRvcDogMTVweDtcbiAgICBwYWRkaW5nLWxlZnQ6IDQ2cHg7XG4gICAgcGFkZGluZy1yaWdodDogNDZweDtcbiAgICBib3JkZXI6IG5vbmU7XG59XG5cbi5ib29rRWRpdG9yVGV4dGFyZWE6OnNlbGVjdGlvbiB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg5OSwgMTAyLCAyNDEsIDAuNik7XG59XG5cbi5ib29rRWRpdG9yU2VyaWYge1xuICAgIGZvbnQtZmFtaWx5OiB1aS1zZXJpZiwgR2VvcmdpYSwgQ2FtYnJpYSwgJ1RpbWVzIE5ldyBSb21hbicsIFRpbWVzLCBzZXJpZjtcbn1cblxuLmJvb2tFZGl0b3JWZXJzaW9uIHtcbiAgICBmb250LXNpemU6IDAuODc1cmVtO1xuICAgIGNvbG9yOiByZ2JhKDE3LCAyNCwgMzksIDAuNik7XG4gICAgcGFkZGluZzogMC41cmVtIDFyZW07XG4gICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHJnYmEoMjA5LCAyMTMsIDIxOSwgMC44KTtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDk5LCAxMDIsIDI0MSwgMC4xKTtcbn1cblxuLmJvb2tFZGl0b3JWZXJzaW9uIGEge1xuICAgIGNvbG9yOiB1bnNldDtcbiAgICB0ZXh0LWRlY29yYXRpb246IG5vbmU7XG59XG5cbi8qIC0tLSBCb29rIHN5bnRheCBoaWdobGlnaHRpbmcgKi9cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQgOmdsb2JhbCguYm9vay1oaWdobGlnaHQtdGl0bGUpIHtcbiAgICBjb2xvcjogIzMwYThiZDtcbiAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbn1cblxuLmJvb2tFZGl0b3JIaWdobGlnaHQgOmdsb2JhbCguYm9vay1oaWdobGlnaHQta2V5d29yZCkge1xuICAgIGNvbG9yOiAjMzBhOGJkO1xufVxuIl19 */";
1893
2084
  var styles = {"bookEditorContainer":"BookEditor-module_bookEditorContainer__wLMwM","isVerbose":"BookEditor-module_isVerbose__VQ6iL","bookEditorWrapper":"BookEditor-module_bookEditorWrapper__twppD","bookEditorBackground":"BookEditor-module_bookEditorBackground__5O4wu","bookEditorHighlight":"BookEditor-module_bookEditorHighlight__vs37t","bookEditorTextarea":"BookEditor-module_bookEditorTextarea__mUURn","bookEditorSerif":"BookEditor-module_bookEditorSerif__QRS7g","bookEditorVersion":"BookEditor-module_bookEditorVersion__fcjyB"};
1894
2085
  styleInject(css_248z);
1895
2086
 
@@ -2057,12 +2248,17 @@ function BookEditor(props) {
2057
2248
  text.replace(r, (match, ...args) => {
2058
2249
  const index = args[args.length - 2]; // offset
2059
2250
  out += escapeHtml(text.slice(lastIndex, index));
2060
- out += `<span class="text-indigo-700">${escapeHtml(match)}</span>`;
2251
+ out += `<span class="book-highlight-keyword">${escapeHtml(match)}</span>`;
2061
2252
  lastIndex = index + match.length;
2062
2253
  return match;
2063
2254
  });
2064
2255
  out += escapeHtml(text.slice(lastIndex));
2065
- return out;
2256
+ // Highlight the first line
2257
+ const lines = out.split('\n');
2258
+ if (lines.length > 0) {
2259
+ lines[0] = `<span class="book-highlight-title">${lines[0]}</span>`;
2260
+ }
2261
+ return lines.join('\n');
2066
2262
  }, [value, typeRegex]);
2067
2263
  // Host div that will get a shadow root
2068
2264
  const hostRef = useRef(null);
@@ -2104,5 +2300,5 @@ function BookEditor(props) {
2104
2300
  return (jsx("div", { "data-book-component": "BookEditor", "data-nonce": nonce, ref: hostRef, className: classNames(className, isVerbose && styles.isVerbose), children: shadowRootRef.current === null ? jsx(Fragment, { children: "Loading..." }) : createPortal(editorInner, shadowRootRef.current) }));
2105
2301
  }
2106
2302
 
2107
- export { AvatarChip, BOOK_LANGUAGE_VERSION, BookEditor, DEFAULT_BOOK_FONT_CLASS, PROMPTBOOK_ENGINE_VERSION };
2303
+ export { AvatarChip, AvatarChipFromSource, BOOK_LANGUAGE_VERSION, BookEditor, DEFAULT_BOOK_FONT_CLASS, PROMPTBOOK_ENGINE_VERSION };
2108
2304
  //# sourceMappingURL=index.es.js.map