Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/lib/helpers/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const richType = {
Generic: 'generic_template',
Upload: 'upload_template',
ProgramCode: 'program_code',
Embedding: 'embedding_template'
}
export const RichType = Object.freeze(richType);

Expand Down
27 changes: 27 additions & 0 deletions src/lib/helpers/types/conversationTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,33 @@ IRichContent.prototype.code_script;
*/
IRichContent.prototype.language;

/**
* The URL of the embedding rich content.
*
* @name url
* @type {string}
* @instance
*/
IRichContent.prototype.url;

/**
* The title of the embedding rich content.
*
* @name title
* @type {string}
* @instance
*/
IRichContent.prototype.title;

/**
* The html tag of the embedding rich content.
*
* @name html_tag
* @type {string}
* @instance
*/
IRichContent.prototype.html_tag;


/**
* @typedef {Object} TextMessage
Expand Down
1 change: 1 addition & 0 deletions src/lib/scss/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ File: Main Css File
@import "custom/components/markdown";
@import "custom/components/state";
@import "custom/components/codeScript";
@import "custom/components/rich_content";

/* Plugins */
@import "custom/plugins/custom-scrollbar";
Expand Down
89 changes: 89 additions & 0 deletions src/lib/scss/custom/components/_rich_content.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.rc-embedding-wrapper {
width: 100%;
margin-top: 8px;
display: flex;
flex-direction: column;
align-items: center;

.rc-embedding-toggle-group {
display: inline-flex;
align-items: center;
gap: 6px;
}

.rc-embedding-link {
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--bs-info, #50a5f1);
font-size: 16px;
transition: color 0.2s ease;
text-decoration: none;

&:hover {
color: darken(#50a5f1, 15%);
}
}

.rc-embedding-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
margin: 0 auto;
width: auto;
background: linear-gradient(135deg, rgba(244, 106, 106, 0.08), rgba(244, 106, 106, 0.15));
border: 1px solid rgba(244, 106, 106, 0.2);
border-radius: 20px;
cursor: pointer;
padding: 6px 16px;
font-size: 13px;
font-weight: 500;
color: var(--bs-danger, #f46a6a);
user-select: none;
transition: all 0.25s ease;
backdrop-filter: blur(4px);

&:hover {
background: linear-gradient(135deg, rgba(244, 106, 106, 0.15), rgba(244, 106, 106, 0.25));
border-color: rgba(244, 106, 106, 0.4);
box-shadow: 0 2px 8px rgba(244, 106, 106, 0.2);
transform: translateY(-1px);
}

&:active {
transform: translateY(0);
box-shadow: none;
}

&.closed {
background: linear-gradient(135deg, rgba(52, 195, 143, 0.08), rgba(52, 195, 143, 0.15));
border-color: rgba(52, 195, 143, 0.2);
color: var(--bs-success, #34c38f);

&:hover {
background: linear-gradient(135deg, rgba(52, 195, 143, 0.15), rgba(52, 195, 143, 0.25));
border-color: rgba(52, 195, 143, 0.4);
box-shadow: 0 2px 8px rgba(52, 195, 143, 0.2);
}
}
}

.rc-embedding-container {
width: 100%;
border-radius: 8px;
display: flex;
justify-content: center;
overflow: auto;
scrollbar-width: thin;

.rc-embedding-iframe {
width: fit-content;
min-width: 100%;
max-height: 800px;
min-height: 500px;
border: 1px solid var(--bs-border-color, #dee2e6);
border-radius: 8px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script>
import collapse from 'svelte-collapse';

/**
* @type {{
* url?: string,
* title?: string,
* htmlTag?: string
* }}
*/
let {
url = '',
title = '',
htmlTag = ''
} = $props();

let open = $state(false);

function toggleCollapse() {
open = !open;
}
</script>

{#if htmlTag && url}
<div class="rc-embedding-wrapper">
<div class="rc-embedding-toggle-group">
<button type="button" class="rc-embedding-toggle" class:closed={!open} onclick={toggleCollapse}>
<span>{open ? 'Close' : 'Open'}{title ? ` ${title}` : ''}</span>
</button>
<a href={url} target="_blank" rel="noopener noreferrer" class="rc-embedding-link" title="Open in new tab">
<i class="bx bx-link-external"></i>
</a>
</div>
<div use:collapse={{ open, duration: 0.3, easing: 'ease' }} style="width: 100%; margin-top: 8px;">
<div class="rc-embedding-container">
{#if htmlTag === 'iframe'}
<iframe
src={url}
title={title || ''}
frameborder="0"
allowfullscreen
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
class="rc-embedding-iframe"
></iframe>
{/if}
</div>
</div>
</div>
{/if}

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { EditorType, RichType } from "$lib/helpers/enums";
import RcPlainOptions from "./rc-plain-options.svelte";
import RcComplexOptions from "./rc-complex-options.svelte";
import RcEmbedding from "./rc-embedding.svelte";
import ChatAttachmentOptions from "../chat-util/chat-attachment-options.svelte";

/**
Expand Down Expand Up @@ -47,13 +48,12 @@
</script>



{#if message?.rich_content?.editor === EditorType.File}
<ChatAttachmentOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{:else if message?.rich_content?.message?.rich_type === RichType.Embedding}
<RcEmbedding url={message?.rich_content?.message?.url} title={message?.rich_content?.message?.title} htmlTag={message?.rich_content?.message?.html_tag} />
{:else if !resolvedOptions.isComplexElement}
<RcPlainOptions options={resolvedOptions.options} isMultiSelect={resolvedOptions.isMultiSelect} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{:else}
{#if !resolvedOptions.isComplexElement}
<RcPlainOptions options={resolvedOptions.options} isMultiSelect={resolvedOptions.isMultiSelect} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{:else}
<RcComplexOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{/if}
<RcComplexOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{/if}
Loading