@promptbook/components 0.112.0-97 → 0.112.0-99
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 +34 -11
- package/esm/index.es.js.map +1 -1
- package/esm/src/book-components/Chat/Chat/ChatActionsBar.d.ts +2 -0
- package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +6 -0
- package/esm/src/book-components/Chat/save/_common/ChatSaveFormatHandler.d.ts +35 -0
- package/esm/src/book-components/Chat/save/_common/createChatExportFilename.d.ts +11 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +34 -11
- package/umd/index.umd.js.map +1 -1
- package/umd/src/book-components/Chat/Chat/ChatActionsBar.d.ts +2 -0
- package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +6 -0
- package/umd/src/book-components/Chat/save/_common/ChatSaveFormatHandler.d.ts +35 -0
- package/umd/src/book-components/Chat/save/_common/createChatExportFilename.d.ts +11 -0
- package/umd/src/version.d.ts +1 -1
- /package/esm/src/conversion/validation/{_importPipeline.d.ts → _importPipeline.test.d.ts} +0 -0
- /package/umd/src/conversion/validation/{_importPipeline.d.ts → _importPipeline.test.d.ts} +0 -0
package/esm/index.es.js
CHANGED
|
@@ -42,7 +42,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
42
42
|
* @generated
|
|
43
43
|
* @see https://github.com/webgptorg/promptbook
|
|
44
44
|
*/
|
|
45
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
45
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-99';
|
|
46
46
|
/**
|
|
47
47
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
48
48
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -26144,6 +26144,24 @@ const ResetIcon = () => (jsx("svg", { width: "16", height: "16", viewBox: "0 0 2
|
|
|
26144
26144
|
*/
|
|
26145
26145
|
const TemplateIcon = ({ size }) => (jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M18,20H6V4H13V9H18V20Z" }) }));
|
|
26146
26146
|
|
|
26147
|
+
/**
|
|
26148
|
+
* Builds one normalized filename for a chat export download.
|
|
26149
|
+
*
|
|
26150
|
+
* @param title - Human-readable chat title.
|
|
26151
|
+
* @param fileExtension - Output file extension without a leading dot.
|
|
26152
|
+
* @param date - Export date used in the filename.
|
|
26153
|
+
* @returns Stable filename suitable for browser downloads and HTTP headers.
|
|
26154
|
+
*
|
|
26155
|
+
* @private Internal helper shared by chat export flows.
|
|
26156
|
+
*/
|
|
26157
|
+
function createChatExportFilename(title, fileExtension, date = new Date()) {
|
|
26158
|
+
const dateName = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
|
|
26159
|
+
.getDate()
|
|
26160
|
+
.toString()
|
|
26161
|
+
.padStart(2, '0')}`;
|
|
26162
|
+
return `${normalizeToKebabCase(title)}-${dateName}.${fileExtension}`;
|
|
26163
|
+
}
|
|
26164
|
+
|
|
26147
26165
|
/**
|
|
26148
26166
|
* Maximum number of characters shown for a simplified knowledge label.
|
|
26149
26167
|
*
|
|
@@ -28183,7 +28201,7 @@ function getChatSaveFormatDefinitions(formatNames) {
|
|
|
28183
28201
|
*/
|
|
28184
28202
|
function ChatActionsBar(props) {
|
|
28185
28203
|
var _a;
|
|
28186
|
-
const { actionsRef, actionsContainer, messages, participants, title, onReset, resetRequiresConfirmation = true, newChatButtonHref, onUseTemplate, extraActions, saveFormats, isSaveButtonEnabled, shouldFadeActions, shouldDisableActions, chatUiTranslations, onButtonClick, } = props;
|
|
28204
|
+
const { actionsRef, actionsContainer, messages, participants, title, onReset, resetRequiresConfirmation = true, newChatButtonHref, onUseTemplate, extraActions, saveFormats, saveFormatHandlers, isSaveButtonEnabled, shouldFadeActions, shouldDisableActions, chatUiTranslations, onButtonClick, } = props;
|
|
28187
28205
|
const [showSaveMenu, setShowSaveMenu] = useState(false);
|
|
28188
28206
|
useEffect(() => {
|
|
28189
28207
|
const handleKeyDown = (event) => {
|
|
@@ -28199,21 +28217,26 @@ function ChatActionsBar(props) {
|
|
|
28199
28217
|
};
|
|
28200
28218
|
}, []);
|
|
28201
28219
|
const handleDownload = useCallback(async (format) => {
|
|
28220
|
+
const customSaveFormatHandler = saveFormatHandlers === null || saveFormatHandlers === void 0 ? void 0 : saveFormatHandlers[format];
|
|
28221
|
+
if (customSaveFormatHandler) {
|
|
28222
|
+
await customSaveFormatHandler({
|
|
28223
|
+
title,
|
|
28224
|
+
messages,
|
|
28225
|
+
participants,
|
|
28226
|
+
});
|
|
28227
|
+
setShowSaveMenu(false);
|
|
28228
|
+
return;
|
|
28229
|
+
}
|
|
28202
28230
|
const formatDefinition = getChatSaveFormatDefinitions([format])[0];
|
|
28203
28231
|
if (!formatDefinition) {
|
|
28204
28232
|
return;
|
|
28205
28233
|
}
|
|
28206
|
-
const date = new Date();
|
|
28207
|
-
const dateName = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
|
|
28208
|
-
.getDate()
|
|
28209
|
-
.toString()
|
|
28210
|
-
.padStart(2, '0')}`;
|
|
28211
28234
|
const content = await formatDefinition.getContent({ title, messages, participants });
|
|
28212
28235
|
const blob = new Blob([content], { type: formatDefinition.mimeType });
|
|
28213
28236
|
const url = URL.createObjectURL(blob);
|
|
28214
28237
|
const link = document.createElement('a');
|
|
28215
28238
|
link.href = url;
|
|
28216
|
-
link.download =
|
|
28239
|
+
link.download = createChatExportFilename(title, formatDefinition.fileExtension);
|
|
28217
28240
|
document.body.appendChild(link);
|
|
28218
28241
|
link.click();
|
|
28219
28242
|
setTimeout(() => {
|
|
@@ -28221,7 +28244,7 @@ function ChatActionsBar(props) {
|
|
|
28221
28244
|
URL.revokeObjectURL(url);
|
|
28222
28245
|
}, 100);
|
|
28223
28246
|
setShowSaveMenu(false);
|
|
28224
|
-
}, [messages, participants, title]);
|
|
28247
|
+
}, [messages, participants, saveFormatHandlers, title]);
|
|
28225
28248
|
const firstMessageFromUser = ((_a = messages[0]) === null || _a === void 0 ? void 0 : _a.sender) === 'USER';
|
|
28226
28249
|
const actionsAlignmentClass = classNames(styles$5.actions, firstMessageFromUser ? styles$5.left : styles$5.right);
|
|
28227
28250
|
const newChatButtonLabel = (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.newChatButtonLabel) || 'New chat';
|
|
@@ -40014,7 +40037,7 @@ function hasChatActions(postprocessedMessages, { onReset, newChatButtonHref, onU
|
|
|
40014
40037
|
* @public exported from `@promptbook/components`
|
|
40015
40038
|
*/
|
|
40016
40039
|
function Chat(props) {
|
|
40017
|
-
const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, layout, visualMode = 'ARTICLE_MODE', theme = 'LIGHT', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
40040
|
+
const { title = 'Chat', messages, onChange, onMessage, onActionButton, onQuickMessageButton, onReplyToMessage, onCancelReply, onReset, resetRequiresConfirmation = true, newChatButtonHref, onFeedback, feedbackMode = 'stars', feedbackTranslations, timingTranslations, onFileUpload, chatLocale, speechRecognition, placeholderMessageContent, defaultMessage, enterBehavior, resolveEnterBehavior, children, className, style, isAiTextHumanizedAndPromptbookified = true, isVoiceCalling = false, isFocusedOnLoad, participants = [], canReplyToMessage, replyingToMessage, extraActions, actionsContainer, saveFormats, saveFormatHandlers, isSaveButtonEnabled = true, isCopyButtonEnabled = true, buttonColor: buttonColorRaw, onUseTemplate, onCreateAgent, toolTitles, teammates, teamAgentProfiles, layout, visualMode = 'ARTICLE_MODE', theme = 'LIGHT', effectConfigs, soundSystem, speechRecognitionLanguage, isSpeechPlaybackEnabled = true, elevenLabsVoiceId, chatUiTranslations, } = props;
|
|
40018
40041
|
const buttonColor = useMemo(() => Color.from(buttonColorRaw || '#0066cc'), [buttonColorRaw]);
|
|
40019
40042
|
const agentParticipant = useMemo(() => participants.find((participant) => participant.name === 'AGENT'), [participants]);
|
|
40020
40043
|
const postprocessedMessages = useChatPostprocessedMessages({
|
|
@@ -40059,7 +40082,7 @@ function Chat(props) {
|
|
|
40059
40082
|
useChatCompleteNotification(messages, soundSystem);
|
|
40060
40083
|
return (jsxs(Fragment, { children: [feedbackStatus && (jsx("div", { className: classNames(styles$5.feedbackStatus, feedbackStatus.variant === 'success'
|
|
40061
40084
|
? styles$5.feedbackStatusSuccess
|
|
40062
|
-
: styles$5.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$5.Chat, layout === 'STANDALONE' && styles$5.standaloneVisual, layout === 'FULL_PAGE' && styles$5.fullPageVisual, isConstrainedArticleMode && styles$5.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), "data-chat-theme": mode.toLowerCase(), style, children: jsxs("div", { className: classNames(className, styles$5.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$5.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$5.scrollToBottomContainer, children: jsxs("div", { className: styles$5.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$5.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$5.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$5.voiceCallIndicatorBar, children: jsxs("div", { className: styles$5.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$5.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools, mode: mode }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
|
|
40085
|
+
: styles$5.feedbackStatusError), "aria-live": "polite", role: "status", children: feedbackStatus.message })), effectConfigs && effectConfigs.length > 0 && (jsx(ChatEffectsSystem, { messages: postprocessedMessages, effectConfigs: effectConfigs, soundSystem: soundSystem })), jsx("div", { className: classNames(className, styles$5.Chat, layout === 'STANDALONE' && styles$5.standaloneVisual, layout === 'FULL_PAGE' && styles$5.fullPageVisual, isConstrainedArticleMode && styles$5.constrainedArticleVisual, getChatCssClassName('Chat'), chatCssClassNames.chat), "data-chat-theme": mode.toLowerCase(), style, children: jsxs("div", { className: classNames(className, styles$5.chatMainFlow, getChatCssClassName('chatMainFlow'), chatCssClassNames.chatMainFlow), children: [children && jsx("div", { className: classNames(styles$5.chatChildren), children: children }), shouldShowScrollToBottom && (jsx("div", { className: styles$5.scrollToBottomContainer, children: jsxs("div", { className: styles$5.scrollToBottomWrapper, children: [jsx(SolidArrowButton, { "data-button-type": "custom", direction: "down", iconSize: 33, className: classNames(styles$5.scrollToBottom, scrollToBottomCssClassName), onClick: handleButtonClick(() => scrollToBottom()), "aria-label": ariaLabel, title: ariaLabel }), badgeLabel && (jsx("span", { className: styles$5.scrollToBottomBadge, "aria-live": "polite", role: "status", children: badgeLabel }))] }) })), isVoiceCalling && (jsx("div", { className: styles$5.voiceCallIndicatorBar, children: jsxs("div", { className: styles$5.voiceCallIndicator, children: [jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: jsx("path", { d: "M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z" }) }), jsx("span", { children: "Voice call active" }), jsx("div", { className: styles$5.voiceCallPulse })] }) })), jsx(ChatActionsBar, { actionsRef: actionsRef, actionsContainer: actionsContainer, messages: postprocessedMessages, participants: participants, title: title, onReset: onReset, resetRequiresConfirmation: resetRequiresConfirmation, newChatButtonHref: newChatButtonHref, onUseTemplate: onUseTemplate, extraActions: extraActions, saveFormats: saveFormats, saveFormatHandlers: saveFormatHandlers, isSaveButtonEnabled: isSaveButtonEnabled, shouldFadeActions: shouldFadeActions, shouldDisableActions: shouldDisableActions, chatUiTranslations: chatUiTranslations, onButtonClick: handleButtonClick }), jsx(ChatMessageList, { messages: postprocessedMessages, participants: participants, expandedMessageId: expandedMessageId, messageRatings: messageRatings, setExpandedMessageId: setExpandedMessageId, handleRating: handleRating, mode: mode, isCopyButtonEnabled: isCopyButtonEnabled, isFeedbackEnabled: isFeedbackEnabled, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, timingTranslations: timingTranslations, chatLocale: chatLocale, onCopy: handleCopy, onMessage: onMessage, onActionButton: onActionButton, onQuickMessageButton: onQuickMessageButton, onReplyToMessage: onReplyToMessage, canReplyToMessage: canReplyToMessage, onCreateAgent: onCreateAgent, toolTitles: toolTitles, teammates: teammates, teamAgentProfiles: teamAgentProfiles, visualMode: visualMode, soundSystem: soundSystem, onToolCallClick: openToolCall, onCitationClick: openCitation, setChatMessagesElement: setChatMessagesElement, onScroll: handleChatScroll, isSpeechPlaybackEnabled: isSpeechPlaybackEnabled, elevenLabsVoiceId: elevenLabsVoiceId, chatUiTranslations: chatUiTranslations, chatMessagesClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatMessages, getChatCssClassName('chatMessages'), chatCssClassNames.chatMessages), hasActions: hasActions }), onMessage && (jsx(ChatInputArea, { onMessage: onMessage, onChange: onChange, onFileUpload: onFileUpload, speechRecognition: speechRecognition, speechRecognitionLanguage: speechRecognitionLanguage, replyingToMessage: replyingToMessage, onCancelReply: onCancelReply, defaultMessage: defaultMessage, enterBehavior: enterBehavior, resolveEnterBehavior: resolveEnterBehavior, placeholderMessageContent: placeholderMessageContent || (chatUiTranslations === null || chatUiTranslations === void 0 ? void 0 : chatUiTranslations.inputPlaceholder), isFocusedOnLoad: isFocusedOnLoad, isMobile: isMobile, isVoiceCalling: isVoiceCalling, participants: participants, buttonColor: buttonColor, soundSystem: soundSystem, onButtonClick: handleButtonClick, chatUiTranslations: chatUiTranslations, chatInputClassName: classNames(isConstrainedArticleMode && styles$5.articleModeChatInput, getChatCssClassName('chatInput'), chatCssClassNames.chatInput) }))] }) }), jsx(ChatToolCallModal, { isOpen: toolCallModalOpen, toolCall: selectedToolCall, toolCallIdentity: selectedToolCallIdentity, onClose: closeToolCallModal, toolTitles: toolTitles, agentParticipant: agentParticipant, buttonColor: buttonColor, teamAgentProfiles: teamAgentProfiles, chatUiTranslations: chatUiTranslations, locale: chatLocale, availableTools: selectedMessageAvailableTools, mode: mode }), jsx(ChatCitationModal, { isOpen: citationModalOpen, citation: selectedCitation, participants: participants, soundSystem: soundSystem, onClose: closeCitationModal }), jsx(ChatRatingModal, { isOpen: ratingModalOpen, selectedMessage: selectedMessage, postprocessedMessages: postprocessedMessages, messages: messages, hoveredRating: hoveredRating, messageRatings: messageRatings, textRating: textRating, feedbackMode: feedbackMode, feedbackTranslations: feedbackTranslations, mode: mode, isMobile: isMobile, onClose: () => setRatingModalOpen(false), setHoveredRating: setHoveredRating, setMessageRatings: setMessageRatings, setSelectedMessage: setSelectedMessage, setTextRating: setTextRating, submitRating: submitRating })] }));
|
|
40063
40086
|
}
|
|
40064
40087
|
|
|
40065
40088
|
/**
|