mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-06 08:50:50 +08:00
refactor: move ai-item components to frontend core (#10369)
### TL;DR Relocated AI item components from BlockSuite to the frontend codebase and updated related imports. ### What changed? - Moved AI item components from `blocksuite/affine/components/src/ai-item` to `packages/frontend/core/src/blocksuite/presets/ai/_common/components/ai-item` - Updated all imports referencing the old AI item component location to point to the new location - Removed AI item exports from BlockSuite's package.json and effects registration - Added AI item effects registration to frontend presets ### How to test? 1. Verify AI functionality works as expected in: - Chat panels - AI toolbars - Edgeless copilot - Slash menu 2. Confirm no AI-related console errors appear 3. Test error handling scenarios (unauthorized, payment required, network errors) ### Why make this change? This change consolidates AI-related components into the frontend codebase where they are primarily used, rather than keeping them in BlockSuite. This improves code organization by placing components closer to their implementation and usage, while reducing unnecessary coupling between packages.
This commit is contained in:
+147
@@ -0,0 +1,147 @@
|
||||
import {
|
||||
EditorHost,
|
||||
PropTypes,
|
||||
requiredProperties,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import { createLitPortal } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
import type { AIItem } from './ai-item';
|
||||
import { SUBMENU_OFFSET_CROSS_AXIS, SUBMENU_OFFSET_MAIN_AXIS } from './const';
|
||||
import type { AIItemConfig, AIItemGroupConfig } from './types';
|
||||
|
||||
@requiredProperties({ host: PropTypes.instanceOf(EditorHost) })
|
||||
export class AIItemList extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
width: 100%;
|
||||
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
|
||||
user-select: none;
|
||||
}
|
||||
.group-name {
|
||||
display: flex;
|
||||
padding: 4px calc(var(--item-padding, 8px) + 4px);
|
||||
align-items: center;
|
||||
color: var(--affine-text-secondary-color);
|
||||
text-align: justify;
|
||||
font-size: var(--affine-font-xs);
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
`;
|
||||
|
||||
private _abortController: AbortController | null = null;
|
||||
|
||||
private _activeSubMenuItem: AIItemConfig | null = null;
|
||||
|
||||
private readonly _closeSubMenu = () => {
|
||||
if (this._abortController) {
|
||||
this._abortController.abort();
|
||||
this._abortController = null;
|
||||
}
|
||||
this._activeSubMenuItem = null;
|
||||
};
|
||||
|
||||
private readonly _itemClassName = (item: AIItemConfig) => {
|
||||
return 'ai-item-' + item.name.split(' ').join('-').toLocaleLowerCase();
|
||||
};
|
||||
|
||||
private readonly _openSubMenu = (item: AIItemConfig) => {
|
||||
if (!item.subItem || item.subItem.length === 0) {
|
||||
this._closeSubMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
if (item === this._activeSubMenuItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aiItem = this.shadowRoot?.querySelector(
|
||||
`.${this._itemClassName(item)}`
|
||||
) as AIItem | null;
|
||||
if (!aiItem || !aiItem.menuItem) return;
|
||||
|
||||
this._closeSubMenu();
|
||||
this._activeSubMenuItem = item;
|
||||
this._abortController = new AbortController();
|
||||
this._abortController.signal.addEventListener('abort', () => {
|
||||
this._closeSubMenu();
|
||||
});
|
||||
|
||||
const aiItemContainer = aiItem.menuItem;
|
||||
const subMenuOffset = {
|
||||
mainAxis: item.subItemOffset?.[0] ?? SUBMENU_OFFSET_MAIN_AXIS,
|
||||
crossAxis: item.subItemOffset?.[1] ?? SUBMENU_OFFSET_CROSS_AXIS,
|
||||
};
|
||||
|
||||
createLitPortal({
|
||||
template: html`<ai-sub-item-list
|
||||
.item=${item}
|
||||
.host=${this.host}
|
||||
.onClick=${this.onClick}
|
||||
.abortController=${this._abortController}
|
||||
></ai-sub-item-list>`,
|
||||
container: aiItemContainer,
|
||||
positionStrategy: 'fixed',
|
||||
computePosition: {
|
||||
referenceElement: aiItemContainer,
|
||||
placement: 'right-start',
|
||||
middleware: [flip(), offset(subMenuOffset)],
|
||||
autoUpdate: true,
|
||||
},
|
||||
abortController: this._abortController,
|
||||
closeOnClickAway: true,
|
||||
});
|
||||
};
|
||||
|
||||
override render() {
|
||||
return html`${repeat(this.groups, group => {
|
||||
return html`
|
||||
${group.name
|
||||
? html`<div class="group-name">
|
||||
${group.name.toLocaleUpperCase()}
|
||||
</div>`
|
||||
: nothing}
|
||||
${repeat(
|
||||
group.items,
|
||||
item =>
|
||||
html`<ai-item
|
||||
.onClick=${this.onClick}
|
||||
.item=${item}
|
||||
.host=${this.host}
|
||||
class=${this._itemClassName(item)}
|
||||
@mouseover=${() => {
|
||||
this._openSubMenu(item);
|
||||
}}
|
||||
></ai-item>`
|
||||
)}
|
||||
`;
|
||||
})}`;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor groups: AIItemGroupConfig[] = [];
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor host!: EditorHost;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onClick: (() => void) | undefined = undefined;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'ai-item-list': AIItemList;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import {
|
||||
EditorHost,
|
||||
PropTypes,
|
||||
requiredProperties,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import { ArrowRightIcon, EnterIcon } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
|
||||
import { menuItemStyles } from './styles';
|
||||
import type { AIItemConfig } from './types';
|
||||
|
||||
@requiredProperties({
|
||||
host: PropTypes.instanceOf(EditorHost),
|
||||
item: PropTypes.object,
|
||||
})
|
||||
export class AIItem extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
${menuItemStyles}
|
||||
`;
|
||||
|
||||
override render() {
|
||||
const { item } = this;
|
||||
const className = item.name.split(' ').join('-').toLocaleLowerCase();
|
||||
|
||||
return html`<div
|
||||
class="menu-item ${className}"
|
||||
@pointerdown=${(e: MouseEvent) => e.stopPropagation()}
|
||||
@click=${() => {
|
||||
this.onClick?.();
|
||||
if (typeof item.handler === 'function') {
|
||||
item.handler(this.host);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<span class="item-icon">${item.icon}</span>
|
||||
<div class="item-name">
|
||||
${item.name}${item.beta
|
||||
? html`<div class="item-beta">(Beta)</div>`
|
||||
: nothing}
|
||||
</div>
|
||||
${item.subItem
|
||||
? html`<span class="arrow-right-icon">${ArrowRightIcon}</span>`
|
||||
: html`<span class="enter-icon">${EnterIcon}</span>`}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor host!: EditorHost;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor item!: AIItemConfig;
|
||||
|
||||
@query('.menu-item')
|
||||
accessor menuItem: HTMLDivElement | null = null;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onClick: (() => void) | undefined;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'ai-item': AIItem;
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import {
|
||||
EditorHost,
|
||||
PropTypes,
|
||||
requiredProperties,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import { EnterIcon } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
|
||||
import { menuItemStyles } from './styles';
|
||||
import type { AIItemConfig, AISubItemConfig } from './types';
|
||||
|
||||
@requiredProperties({
|
||||
host: PropTypes.instanceOf(EditorHost),
|
||||
item: PropTypes.object,
|
||||
})
|
||||
export class AISubItemList extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
.ai-sub-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
min-width: 240px;
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
background: var(--affine-background-overlay-panel-color);
|
||||
box-shadow: var(--affine-shadow-2);
|
||||
border-radius: 8px;
|
||||
z-index: var(--affine-z-index-popover);
|
||||
font-family: ${unsafeCSS(baseTheme.fontSansFamily)};
|
||||
color: var(--affine-text-primary-color);
|
||||
text-align: justify;
|
||||
font-feature-settings:
|
||||
'clig' off,
|
||||
'liga' off;
|
||||
font-size: var(--affine-font-sm);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
user-select: none;
|
||||
}
|
||||
${menuItemStyles}
|
||||
`;
|
||||
|
||||
private readonly _handleClick = (subItem: AISubItemConfig) => {
|
||||
this.onClick?.();
|
||||
if (subItem.handler) {
|
||||
// TODO: add parameters to ai handler
|
||||
subItem.handler(this.host);
|
||||
}
|
||||
this.abortController.abort();
|
||||
};
|
||||
|
||||
override render() {
|
||||
if (!this.item.subItem || this.item.subItem.length <= 0) return nothing;
|
||||
return html`<div class="ai-sub-menu">
|
||||
${this.item.subItem?.map(
|
||||
subItem =>
|
||||
html`<div
|
||||
class="menu-item"
|
||||
@click=${() => this._handleClick(subItem)}
|
||||
>
|
||||
<div class="item-name">${subItem.type}</div>
|
||||
<span class="enter-icon">${EnterIcon}</span>
|
||||
</div>`
|
||||
)}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor abortController: AbortController = new AbortController();
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor host!: EditorHost;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor item!: AIItemConfig;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor onClick: (() => void) | undefined;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'ai-sub-item-list': AISubItemList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
export const SUBMENU_OFFSET_MAIN_AXIS = 12;
|
||||
export const SUBMENU_OFFSET_CROSS_AXIS = -60;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { AIItem } from './ai-item';
|
||||
import { AIItemList } from './ai-item-list';
|
||||
import { AISubItemList } from './ai-sub-item-list';
|
||||
|
||||
export * from './ai-item-list.js';
|
||||
export * from './types.js';
|
||||
|
||||
export function effects() {
|
||||
customElements.define('ai-item-list', AIItemList);
|
||||
customElements.define('ai-item', AIItem);
|
||||
customElements.define('ai-sub-item-list', AISubItemList);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { css } from 'lit';
|
||||
|
||||
export const menuItemStyles = css`
|
||||
.menu-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 4px var(--item-padding, 12px);
|
||||
gap: 4px;
|
||||
align-self: stretch;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.menu-item:hover {
|
||||
background: var(--affine-hover-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.item-icon {
|
||||
display: flex;
|
||||
color: var(--item-icon-color, var(--affine-brand-color));
|
||||
}
|
||||
.menu-item:hover .item-icon {
|
||||
color: var(--item-icon-hover-color, var(--affine-brand-color));
|
||||
}
|
||||
.menu-item.discard:hover {
|
||||
background: var(--affine-background-error-color);
|
||||
.item-name,
|
||||
.item-icon,
|
||||
.enter-icon {
|
||||
color: var(--affine-error-color);
|
||||
}
|
||||
}
|
||||
.item-name {
|
||||
display: flex;
|
||||
padding: 0px 4px;
|
||||
align-items: baseline;
|
||||
flex: 1 0 0;
|
||||
color: var(--affine-text-primary-color);
|
||||
text-align: start;
|
||||
white-space: nowrap;
|
||||
font-feature-settings:
|
||||
'clig' off,
|
||||
'liga' off;
|
||||
font-size: var(--affine-font-sm);
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.item-beta {
|
||||
color: var(--affine-text-secondary-color);
|
||||
font-size: var(--affine-font-xs);
|
||||
font-weight: 500;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.enter-icon,
|
||||
.arrow-right-icon {
|
||||
color: var(--affine-icon-color);
|
||||
display: flex;
|
||||
}
|
||||
.enter-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
.arrow-right-icon,
|
||||
.menu-item:hover .enter-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,72 @@
|
||||
import type {
|
||||
Chain,
|
||||
EditorHost,
|
||||
InitCommandCtx,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import type { DocMode } from '@blocksuite/affine/blocks';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
export interface AIItemGroupConfig {
|
||||
name?: string;
|
||||
items: AIItemConfig[];
|
||||
}
|
||||
|
||||
export interface AIItemConfig {
|
||||
name: string;
|
||||
icon: TemplateResult | (() => HTMLElement);
|
||||
showWhen?: (
|
||||
chain: Chain<InitCommandCtx>,
|
||||
editorMode: DocMode,
|
||||
host: EditorHost
|
||||
) => boolean;
|
||||
subItem?: AISubItemConfig[];
|
||||
subItemOffset?: [number, number];
|
||||
handler?: (host: EditorHost) => void;
|
||||
beta?: boolean;
|
||||
}
|
||||
|
||||
export interface AISubItemConfig {
|
||||
type: string;
|
||||
handler?: (host: EditorHost) => void;
|
||||
}
|
||||
|
||||
abstract class BaseAIError extends Error {
|
||||
abstract readonly type: AIErrorType;
|
||||
}
|
||||
|
||||
export enum AIErrorType {
|
||||
GeneralNetworkError = 'GeneralNetworkError',
|
||||
PaymentRequired = 'PaymentRequired',
|
||||
Unauthorized = 'Unauthorized',
|
||||
}
|
||||
|
||||
export class UnauthorizedError extends BaseAIError {
|
||||
readonly type = AIErrorType.Unauthorized;
|
||||
|
||||
constructor() {
|
||||
super('Unauthorized');
|
||||
}
|
||||
}
|
||||
|
||||
// user has used up the quota
|
||||
export class PaymentRequiredError extends BaseAIError {
|
||||
readonly type = AIErrorType.PaymentRequired;
|
||||
|
||||
constructor() {
|
||||
super('Payment required');
|
||||
}
|
||||
}
|
||||
|
||||
// general 500x error
|
||||
export class GeneralNetworkError extends BaseAIError {
|
||||
readonly type = AIErrorType.GeneralNetworkError;
|
||||
|
||||
constructor(message: string = 'Network error') {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
export type AIError =
|
||||
| UnauthorizedError
|
||||
| PaymentRequiredError
|
||||
| GeneralNetworkError;
|
||||
+2
-5
@@ -1,11 +1,7 @@
|
||||
import './ask-ai-panel';
|
||||
|
||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIItemGroupConfig,
|
||||
createLitPortal,
|
||||
HoverController,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { createLitPortal, HoverController } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
@@ -13,6 +9,7 @@ import { property, query } from 'lit/decorators.js';
|
||||
import { ref } from 'lit/directives/ref.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { AIItemGroupConfig } from './ai-item/types';
|
||||
import type { ButtonSize } from './ask-ai-icon';
|
||||
|
||||
type toggleType = 'hover' | 'click';
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIItemGroupConfig,
|
||||
DocModeProvider,
|
||||
scrollbarStyle,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { DocModeProvider, scrollbarStyle } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { css, html, LitElement, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { AIItemGroupConfig } from './ai-item/types';
|
||||
|
||||
export class AskAIPanel extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
:host {
|
||||
|
||||
+2
-4
@@ -3,10 +3,7 @@ import {
|
||||
type EditorHost,
|
||||
TextSelection,
|
||||
} from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIItemGroupConfig,
|
||||
createLitPortal,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { createLitPortal } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
@@ -16,6 +13,7 @@ import { AIProvider } from '../../provider';
|
||||
import { getAIPanelWidget } from '../../utils/ai-widgets';
|
||||
import { extractSelectedContent } from '../../utils/extract';
|
||||
import type { AffineAIPanelWidgetConfig } from '../../widgets/ai-panel/type';
|
||||
import type { AIItemGroupConfig } from './ai-item/types';
|
||||
|
||||
export class AskAIToolbarButton extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { Chain, InitCommandCtx } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIItemGroupConfig,
|
||||
type AISubItemConfig,
|
||||
CodeBlockModel,
|
||||
getSelectedModelsCommand,
|
||||
ImageBlockModel,
|
||||
@@ -19,6 +17,10 @@ import {
|
||||
} from '../actions/types';
|
||||
import { AIProvider } from '../provider';
|
||||
import { getAIPanelWidget } from '../utils/ai-widgets';
|
||||
import type {
|
||||
AIItemGroupConfig,
|
||||
AISubItemConfig,
|
||||
} from './components/ai-item/types';
|
||||
import {
|
||||
AIDoneIcon,
|
||||
AIImageIcon,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { type EditorHost, TextSelection } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
type AIItemGroupConfig,
|
||||
AIStarIconWithAnimation,
|
||||
createLitPortal,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
@@ -9,6 +7,10 @@ import { assertExists } from '@blocksuite/affine/global/utils';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { html, type TemplateResult } from 'lit';
|
||||
|
||||
import type {
|
||||
AIError,
|
||||
AIItemGroupConfig,
|
||||
} from '../_common/components/ai-item/types';
|
||||
import {
|
||||
buildCopyConfig,
|
||||
buildErrorConfig,
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
GfxControllerIdentifier,
|
||||
type GfxModel,
|
||||
} from '@blocksuite/affine/block-std/gfx';
|
||||
import type { AIError } from '@blocksuite/affine/blocks';
|
||||
import {
|
||||
CodeBlockModel,
|
||||
EdgelessTextBlockModel,
|
||||
@@ -21,6 +20,7 @@ import type { TemplateResult } from 'lit';
|
||||
|
||||
import { AIChatBlockModel } from '../../../blocks';
|
||||
import { getContentFromSlice } from '../../_common';
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
import { AIProvider } from '../provider';
|
||||
import { reportResponse } from '../utils/action-reporter';
|
||||
import { getAIPanelWidget } from '../utils/ai-widgets';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||
import type {
|
||||
AIItemConfig,
|
||||
EdgelessElementToolbarWidget,
|
||||
MindmapElementModel,
|
||||
ShapeElementModel,
|
||||
@@ -28,6 +27,7 @@ import { html, type TemplateResult } from 'lit';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { insertFromMarkdown } from '../../_common';
|
||||
import type { AIItemConfig } from '../_common/components/ai-item/types';
|
||||
import { AIPenIcon, ChatWithAIIcon } from '../_common/icons';
|
||||
import { AIProvider } from '../provider';
|
||||
import { reportResponse } from '../utils/action-reporter';
|
||||
|
||||
@@ -2,7 +2,6 @@ import { AINetworkSearchService } from '@affine/core/modules/ai-button/services/
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||
import {
|
||||
type AIItemConfig,
|
||||
ImageBlockModel,
|
||||
isInsideEdgelessEditor,
|
||||
matchModels,
|
||||
@@ -14,6 +13,7 @@ import type { FrameworkProvider } from '@toeverything/infra';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
import { createTextRenderer, insertFromMarkdown } from '../_common';
|
||||
import type { AIItemConfig } from './_common/components/ai-item/types';
|
||||
import {
|
||||
AIPenIcon,
|
||||
AIStarIconWithAnimation,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AIError } from '@blocksuite/affine/blocks';
|
||||
import type { Signal } from '@preact/signals-core';
|
||||
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
|
||||
export type ChatMessage = {
|
||||
id: string;
|
||||
content: string;
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { stopPropagation } from '@affine/core/utils';
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
openFileOrFiles,
|
||||
unsafeCSSVarV2,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { openFileOrFiles, unsafeCSSVarV2 } from '@blocksuite/affine/blocks';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { ImageIcon, PublishIcon } from '@blocksuite/icons/lit';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { property, query, state } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
import {
|
||||
ChatAbortIcon,
|
||||
ChatClearIcon,
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import { ShadowlessElement } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
DocModeProvider,
|
||||
FeatureFlagService,
|
||||
isInsidePageEditor,
|
||||
PaymentRequiredError,
|
||||
type SpecBuilder,
|
||||
UnauthorizedError,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import type { BaseSelection } from '@blocksuite/affine/store';
|
||||
@@ -21,6 +18,11 @@ import {
|
||||
EdgelessEditorActions,
|
||||
PageEditorActions,
|
||||
} from '../_common/chat-actions-handle';
|
||||
import {
|
||||
type AIError,
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from '../_common/components/ai-item/types';
|
||||
import { AffineAvatarIcon, AffineIcon, DownArrowIcon } from '../_common/icons';
|
||||
import { AIChatErrorRenderer } from '../messages/error';
|
||||
import { AIProvider } from '../provider';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
type AIItemGroupConfig,
|
||||
AIStarIconWithAnimation,
|
||||
MindmapElementModel,
|
||||
ShapeElementModel,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
TextElementModel,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types';
|
||||
import {
|
||||
AIExpandMindMapIcon,
|
||||
AIImageIcon,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type {
|
||||
AIItemGroupConfig,
|
||||
DocMode,
|
||||
EdgelessElementToolbarWidget,
|
||||
EdgelessRootBlockComponent,
|
||||
@@ -7,6 +6,7 @@ import type {
|
||||
import { noop } from '@blocksuite/affine/global/utils';
|
||||
import { html } from 'lit';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types';
|
||||
import { AIProvider } from '../../provider';
|
||||
import { getAIPanelWidget } from '../../utils/ai-widgets';
|
||||
import { getEdgelessCopilotWidget } from '../../utils/edgeless';
|
||||
|
||||
+1
-1
@@ -4,7 +4,6 @@ import {
|
||||
type AffineSlashMenuItem,
|
||||
AffineSlashMenuWidget,
|
||||
type AffineSlashSubMenu,
|
||||
type AIItemConfig,
|
||||
AIStarIcon,
|
||||
DocModeProvider,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
@@ -12,6 +11,7 @@ import { assertExists } from '@blocksuite/affine/global/utils';
|
||||
import { MoreHorizontalIcon } from '@blocksuite/icons/lit';
|
||||
import { html } from 'lit';
|
||||
|
||||
import type { AIItemConfig } from '../../_common/components/ai-item/types';
|
||||
import { pageAIGroups } from '../../_common/config';
|
||||
import { handleInlineAskAIAction } from '../../actions/doc-handler';
|
||||
import { AIProvider } from '../../provider';
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
PaymentRequiredError,
|
||||
scrollbarStyle,
|
||||
UnauthorizedError,
|
||||
unsafeCSSVarV2,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { scrollbarStyle, unsafeCSSVarV2 } from '@blocksuite/affine/blocks';
|
||||
import { SignalWatcher, WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { ToggleDownIcon } from '@blocksuite/icons/lit';
|
||||
import { signal } from '@preact/signals-core';
|
||||
@@ -13,6 +7,11 @@ import { baseTheme } from '@toeverything/theme';
|
||||
import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
|
||||
import {
|
||||
type AIError,
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from '../_common/components/ai-item/types';
|
||||
import { ErrorTipIcon } from '../_common/icons';
|
||||
import { AIProvider } from '../provider';
|
||||
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
openFileOrFiles,
|
||||
unsafeCSSVarV2,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { openFileOrFiles, unsafeCSSVarV2 } from '@blocksuite/affine/blocks';
|
||||
import { SignalWatcher } from '@blocksuite/affine/global/utils';
|
||||
import { ImageIcon, PublishIcon } from '@blocksuite/icons/lit';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
@@ -11,6 +7,7 @@ import { property, query, state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
|
||||
import type { ChatMessage } from '../../../blocks';
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
import { ChatAbortIcon, ChatClearIcon, ChatSendIcon } from '../_common/icons';
|
||||
import type { AINetworkSearchConfig } from '../chat-panel/chat-config';
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { type EditorHost } from '@blocksuite/affine/block-std';
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
type AIError,
|
||||
CanvasElementType,
|
||||
ConnectorMode,
|
||||
DocModeProvider,
|
||||
@@ -26,6 +25,7 @@ import {
|
||||
constructUserInfoWithMessages,
|
||||
queryHistoryMessages,
|
||||
} from '../_common/chat-actions-handle';
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
import { SmallHintIcon } from '../_common/icons';
|
||||
import type { AINetworkSearchConfig } from '../chat-panel/chat-config';
|
||||
import { AIChatErrorRenderer } from '../messages/error';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { AIError } from '@blocksuite/affine/blocks';
|
||||
|
||||
import type { ChatMessage } from '../../../blocks';
|
||||
import type { AIError } from '../_common/components/ai-item/types';
|
||||
|
||||
export type ChatStatus =
|
||||
| 'success'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import {
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { Slot } from '@blocksuite/affine/global/utils';
|
||||
import { captureException } from '@sentry/react';
|
||||
|
||||
import {
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from './_common/components/ai-item/types';
|
||||
import type { ChatContextValue } from './chat-panel/chat-context';
|
||||
|
||||
export interface AIUserInfo {
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
AFFINE_FORMAT_BAR_WIDGET,
|
||||
AFFINE_VIEWPORT_OVERLAY_WIDGET,
|
||||
type AffineViewportOverlayWidget,
|
||||
type AIError,
|
||||
DocModeProvider,
|
||||
getPageRootByElement,
|
||||
NotificationProvider,
|
||||
@@ -27,6 +26,7 @@ import { css, html, nothing, type PropertyValues } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
import { choose } from 'lit/directives/choose.js';
|
||||
|
||||
import type { AIError } from '../../_common/components/ai-item/types.js';
|
||||
import type { AIPanelGenerating } from './components/index.js';
|
||||
import type { AffineAIPanelState, AffineAIPanelWidgetConfig } from './type.js';
|
||||
|
||||
|
||||
+4
-1
@@ -1,11 +1,14 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import { AIErrorType, type AIItemGroupConfig } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { baseTheme } from '@toeverything/theme';
|
||||
import { css, html, LitElement, nothing, unsafeCSS } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { choose } from 'lit/directives/choose.js';
|
||||
|
||||
import {
|
||||
AIErrorType,
|
||||
type AIItemGroupConfig,
|
||||
} from '../../../../_common/components/ai-item/types.js';
|
||||
import type { AIPanelErrorConfig, CopyConfig } from '../../type.js';
|
||||
import { filterAIItemGroup } from '../../utils.js';
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import type { AIError, AIItemGroupConfig } from '@blocksuite/affine/blocks';
|
||||
import type { Signal } from '@preact/signals-core';
|
||||
import type { nothing, TemplateResult } from 'lit';
|
||||
|
||||
import type {
|
||||
AIError,
|
||||
AIItemGroupConfig,
|
||||
} from '../../_common/components/ai-item/types';
|
||||
|
||||
export interface CopyConfig {
|
||||
allowed: boolean;
|
||||
onCopy: () => boolean | Promise<boolean>;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import type { AIItemGroupConfig } from '@blocksuite/affine/blocks';
|
||||
import { isInsidePageEditor } from '@blocksuite/affine/blocks';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types';
|
||||
|
||||
export function filterAIItemGroup(
|
||||
host: EditorHost,
|
||||
configs: AIItemGroupConfig[]
|
||||
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
||||
import type { AIItemGroupConfig } from '@blocksuite/affine/blocks';
|
||||
import { on, scrollbarStyle, stopPropagation } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { css, html, LitElement, nothing } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types';
|
||||
|
||||
export class EdgelessCopilotPanel extends WithDisposable(LitElement) {
|
||||
static override styles = css`
|
||||
:host {
|
||||
|
||||
+1
-1
@@ -3,12 +3,12 @@ import {
|
||||
GfxControllerIdentifier,
|
||||
isGfxGroupCompatibleModel,
|
||||
} from '@blocksuite/affine/block-std/gfx';
|
||||
import type { AIItemGroupConfig } from '@blocksuite/affine/blocks';
|
||||
import { AIStarIcon, sortEdgelessElements } from '@blocksuite/affine/blocks';
|
||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||
import { css, html, LitElement } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types';
|
||||
import type { CopilotTool } from '../../tool/copilot-tool';
|
||||
|
||||
export class EdgelessCopilotToolbarEntry extends WithDisposable(LitElement) {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { WidgetComponent } from '@blocksuite/affine/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/affine/block-std/gfx';
|
||||
import type {
|
||||
AIItemGroupConfig,
|
||||
RootBlockModel,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import type { RootBlockModel } from '@blocksuite/affine/blocks';
|
||||
import {
|
||||
EdgelessLegacySlotIdentifier,
|
||||
MOUSE_BUTTON,
|
||||
@@ -26,6 +23,7 @@ import { css, html, nothing } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { AIItemGroupConfig } from '../../_common/components/ai-item/types.js';
|
||||
import {
|
||||
AFFINE_AI_PANEL_WIDGET,
|
||||
AffineAIPanelWidget,
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { ImagePlaceholder } from '../blocks/ai-chat-block/components/image-placeholder';
|
||||
import { UserInfo } from '../blocks/ai-chat-block/components/user-info';
|
||||
import { TextRenderer } from './_common/components/text-renderer';
|
||||
import { effects as componentAiItemEffects } from './ai/_common/components/ai-item';
|
||||
import { AskAIButton } from './ai/_common/components/ask-ai-button';
|
||||
import { AskAIIcon } from './ai/_common/components/ask-ai-icon';
|
||||
import { AskAIPanel } from './ai/_common/components/ask-ai-panel';
|
||||
@@ -61,9 +62,10 @@ import {
|
||||
} from './ai/widgets/edgeless-copilot';
|
||||
import { EdgelessCopilotPanel } from './ai/widgets/edgeless-copilot-panel';
|
||||
import { EdgelessCopilotToolbarEntry } from './ai/widgets/edgeless-copilot-panel/toolbar-entry';
|
||||
|
||||
export function registerBlocksuitePresetsCustomComponents() {
|
||||
registerMiniMindmapBlocks();
|
||||
componentAiItemEffects();
|
||||
|
||||
customElements.define('ask-ai-icon', AskAIIcon);
|
||||
customElements.define('ask-ai-button', AskAIButton);
|
||||
customElements.define('ask-ai-toolbar-button', AskAIToolbarButton);
|
||||
|
||||
+5
-5
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
GeneralNetworkError,
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from '@affine/core/blocksuite/presets/ai/_common/components/ai-item/types';
|
||||
import { showAILoginRequiredAtom } from '@affine/core/components/affine/auth/ai-login-required';
|
||||
import {
|
||||
addContextDocMutation,
|
||||
@@ -20,11 +25,6 @@ import {
|
||||
updateCopilotSessionMutation,
|
||||
UserFriendlyError,
|
||||
} from '@affine/graphql';
|
||||
import {
|
||||
GeneralNetworkError,
|
||||
PaymentRequiredError,
|
||||
UnauthorizedError,
|
||||
} from '@blocksuite/affine/blocks';
|
||||
import { getCurrentStore } from '@toeverything/infra';
|
||||
|
||||
type OptionsField<T extends GraphQLQuery> =
|
||||
|
||||
Reference in New Issue
Block a user