import type { EditorHost } from '@cbi-blocksuite/block-std'; import { WithDisposable } from '@cbi-blocksuite/block-std'; import type { RootService } from '@cbi-blocksuite/blocks'; import { openFileOrFiles } from '@cbi-blocksuite/blocks'; import { css, html, LitElement } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; import { ChatSendIcon, CloseIcon, ImageIcon } from '../_common/icons.js'; const MaximumImageCount = 8; @customElement('chat-panel-input') export class ChatPanelInput extends WithDisposable(LitElement) { static override styles = css` .chat-panel-input { margin-top: 12px; position: relative; } .chat-panel-input-actions { position: absolute; right: 16px; bottom: 6px; display: flex; gap: 8px; align-items: center; } .chat-panel-input-actions svg { cursor: pointer; } .chat-panel-input textarea { resize: none; border-radius: 4px; padding: 8px 12px; width: calc(100% - 32px); min-height: 100px; border: 1px solid var(--affine-border-color); font-size: 14px; font-weight: 400; color: var(--affine-text-primary-color); } textarea::placeholder { font-size: 14px; font-weight: 400; color: var(--affine-placeholder-color); } textarea:focus { border: 1px solid var(--affine-border-color); outline: none; } .chat-panel-images { display: flex; gap: 6px; flex-wrap: wrap; position: relative; } .chat-panel-images img { border-radius: 4px; border: 1px solid var(--affine-border-color); } .close-wrapper { width: 16px; height: 16px; border-radius: 4px; border: 1px solid var(--affine-border-color); justify-content: center; align-items: center; display: none; position: absolute; background-color: var(--affine-white); z-index: 1; } .close-wrapper:hover { background-color: var(--affine-background-error-color); border: 1px solid var(--affine-error-color); } .close-wrapper:hover svg path { fill: var(--affine-error-color); } `; @property({ attribute: false }) host!: EditorHost; @property({ attribute: false }) copilot!: RootService['copilot']; @query('textarea') textarea!: HTMLTextAreaElement; @query('.close-wrapper') closeWrapper!: HTMLDivElement; @state() images: File[] = []; @state() curIndex = -1; @state() isInputEmpty = true; send = () => { const text = this.textarea.value; if (!text) { return; } this.textarea.value = ''; this.isInputEmpty = true; this.images = []; this.copilot.askAI( this.copilot.actions.createCommonTextAction([ { type: 'text', text }, ...this.images.map(image => ({ type: 'image_url' as const, image_url: { url: URL.createObjectURL(image) }, })), ]), text ); }; protected override render() { return html`