mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-17 18:16:15 +08:00
refactor(core): image block use peek view workflow (#7329)
depends on https://github.com/toeverything/blocksuite/pull/7424
This commit is contained in:
Vendored
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@blocksuite/global": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/global": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/store": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/store": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"vitest": "1.6.0"
|
"vitest": "1.6.0"
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
"@affine/debug": "workspace:*",
|
"@affine/debug": "workspace:*",
|
||||||
"@affine/env": "workspace:*",
|
"@affine/env": "workspace:*",
|
||||||
"@affine/templates": "workspace:*",
|
"@affine/templates": "workspace:*",
|
||||||
"@blocksuite/blocks": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/blocks": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/global": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/global": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/store": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/store": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@datastructures-js/binary-search-tree": "^5.3.2",
|
"@datastructures-js/binary-search-tree": "^5.3.2",
|
||||||
"foxact": "^0.2.33",
|
"foxact": "^0.2.33",
|
||||||
"jotai": "^2.8.0",
|
"jotai": "^2.8.0",
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@affine-test/fixtures": "workspace:*",
|
"@affine-test/fixtures": "workspace:*",
|
||||||
"@affine/templates": "workspace:*",
|
"@affine/templates": "workspace:*",
|
||||||
"@blocksuite/block-std": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/block-std": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/presets": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/presets": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@testing-library/react": "^16.0.0",
|
"@testing-library/react": "^16.0.0",
|
||||||
"async-call-rpc": "^6.4.0",
|
"async-call-rpc": "^6.4.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
@@ -75,12 +75,12 @@
|
|||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@blocksuite/block-std": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/block-std": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/blocks": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/blocks": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/global": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/global": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/icons": "2.1.58",
|
"@blocksuite/icons": "2.1.58",
|
||||||
"@blocksuite/presets": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/presets": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/store": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/store": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@storybook/addon-actions": "^7.6.17",
|
"@storybook/addon-actions": "^7.6.17",
|
||||||
"@storybook/addon-essentials": "^7.6.17",
|
"@storybook/addon-essentials": "^7.6.17",
|
||||||
"@storybook/addon-interactions": "^7.6.17",
|
"@storybook/addon-interactions": "^7.6.17",
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
"@affine/graphql": "workspace:*",
|
"@affine/graphql": "workspace:*",
|
||||||
"@affine/i18n": "workspace:*",
|
"@affine/i18n": "workspace:*",
|
||||||
"@affine/templates": "workspace:*",
|
"@affine/templates": "workspace:*",
|
||||||
"@blocksuite/block-std": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/block-std": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/blocks": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/blocks": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/global": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/global": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/icons": "2.1.58",
|
"@blocksuite/icons": "2.1.58",
|
||||||
"@blocksuite/inline": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/inline": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/presets": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/presets": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/store": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/store": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@dnd-kit/core": "^6.1.0",
|
"@dnd-kit/core": "^6.1.0",
|
||||||
"@dnd-kit/modifiers": "^7.0.0",
|
"@dnd-kit/modifiers": "^7.0.0",
|
||||||
"@dnd-kit/sortable": "^8.0.0",
|
"@dnd-kit/sortable": "^8.0.0",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
AffineReference,
|
AffineReference,
|
||||||
type EmbedLinkedDocModel,
|
type EmbedLinkedDocModel,
|
||||||
type EmbedSyncedDocModel,
|
type EmbedSyncedDocModel,
|
||||||
|
type ImageBlockModel,
|
||||||
type SurfaceRefBlockComponent,
|
type SurfaceRefBlockComponent,
|
||||||
type SurfaceRefBlockModel,
|
type SurfaceRefBlockModel,
|
||||||
} from '@blocksuite/blocks';
|
} from '@blocksuite/blocks';
|
||||||
@@ -12,6 +13,7 @@ import type { TemplateResult } from 'lit';
|
|||||||
import { firstValueFrom, map, race } from 'rxjs';
|
import { firstValueFrom, map, race } from 'rxjs';
|
||||||
|
|
||||||
import { resolveLinkToDoc } from '../../navigation';
|
import { resolveLinkToDoc } from '../../navigation';
|
||||||
|
import type { WorkbenchService } from '../../workbench';
|
||||||
|
|
||||||
export type PeekViewTarget =
|
export type PeekViewTarget =
|
||||||
| HTMLElement
|
| HTMLElement
|
||||||
@@ -20,17 +22,28 @@ export type PeekViewTarget =
|
|||||||
| HTMLAnchorElement
|
| HTMLAnchorElement
|
||||||
| { docId: string; blockId?: string };
|
| { docId: string; blockId?: string };
|
||||||
|
|
||||||
export type DocPeekViewInfo = {
|
export interface DocPeekViewInfo {
|
||||||
|
type: 'doc';
|
||||||
docId: string;
|
docId: string;
|
||||||
blockId?: string;
|
blockId?: string;
|
||||||
mode?: DocMode;
|
mode?: DocMode;
|
||||||
xywh?: `[${number},${number},${number},${number}]`;
|
xywh?: `[${number},${number},${number},${number}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ImagePeekViewInfo = {
|
||||||
|
type: 'image';
|
||||||
|
docId: string;
|
||||||
|
blockId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CustomTemplatePeekViewInfo = {
|
||||||
|
type: 'template';
|
||||||
|
template: TemplateResult;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ActivePeekView = {
|
export type ActivePeekView = {
|
||||||
target: PeekViewTarget;
|
target: PeekViewTarget;
|
||||||
info?: DocPeekViewInfo;
|
info: DocPeekViewInfo | ImagePeekViewInfo | CustomTemplatePeekViewInfo;
|
||||||
template?: TemplateResult;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const EMBED_DOC_FLAVOURS = [
|
const EMBED_DOC_FLAVOURS = [
|
||||||
@@ -44,6 +57,12 @@ const isEmbedDocModel = (
|
|||||||
return EMBED_DOC_FLAVOURS.includes(blockModel.flavour);
|
return EMBED_DOC_FLAVOURS.includes(blockModel.flavour);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isImageBlockModel = (
|
||||||
|
blockModel: BlockModel
|
||||||
|
): blockModel is ImageBlockModel => {
|
||||||
|
return blockModel.flavour === 'affine:image';
|
||||||
|
};
|
||||||
|
|
||||||
const isSurfaceRefModel = (
|
const isSurfaceRefModel = (
|
||||||
blockModel: BlockModel
|
blockModel: BlockModel
|
||||||
): blockModel is SurfaceRefBlockModel => {
|
): blockModel is SurfaceRefBlockModel => {
|
||||||
@@ -51,12 +70,20 @@ const isSurfaceRefModel = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
function resolvePeekInfoFromPeekTarget(
|
function resolvePeekInfoFromPeekTarget(
|
||||||
peekTarget?: PeekViewTarget
|
peekTarget: PeekViewTarget,
|
||||||
): DocPeekViewInfo | undefined {
|
template?: TemplateResult
|
||||||
if (!peekTarget) return;
|
): ActivePeekView['info'] | undefined {
|
||||||
|
if (template) {
|
||||||
|
return {
|
||||||
|
type: 'template',
|
||||||
|
template,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (peekTarget instanceof AffineReference) {
|
if (peekTarget instanceof AffineReference) {
|
||||||
if (peekTarget.refMeta) {
|
if (peekTarget.refMeta) {
|
||||||
return {
|
return {
|
||||||
|
type: 'doc',
|
||||||
docId: peekTarget.refMeta.id,
|
docId: peekTarget.refMeta.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -64,6 +91,7 @@ function resolvePeekInfoFromPeekTarget(
|
|||||||
const blockModel = peekTarget.model;
|
const blockModel = peekTarget.model;
|
||||||
if (isEmbedDocModel(blockModel)) {
|
if (isEmbedDocModel(blockModel)) {
|
||||||
return {
|
return {
|
||||||
|
type: 'doc',
|
||||||
docId: blockModel.pageId,
|
docId: blockModel.pageId,
|
||||||
};
|
};
|
||||||
} else if (isSurfaceRefModel(blockModel)) {
|
} else if (isSurfaceRefModel(blockModel)) {
|
||||||
@@ -73,22 +101,31 @@ function resolvePeekInfoFromPeekTarget(
|
|||||||
const docId =
|
const docId =
|
||||||
'doc' in refModel ? refModel.doc.id : refModel.surface.doc.id;
|
'doc' in refModel ? refModel.doc.id : refModel.surface.doc.id;
|
||||||
return {
|
return {
|
||||||
|
type: 'doc',
|
||||||
docId,
|
docId,
|
||||||
mode: 'edgeless',
|
mode: 'edgeless',
|
||||||
xywh: refModel.xywh,
|
xywh: refModel.xywh,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
} else if (isImageBlockModel(blockModel)) {
|
||||||
|
return {
|
||||||
|
type: 'image',
|
||||||
|
docId: blockModel.doc.id,
|
||||||
|
blockId: blockModel.id,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else if (peekTarget instanceof HTMLAnchorElement) {
|
} else if (peekTarget instanceof HTMLAnchorElement) {
|
||||||
const maybeDoc = resolveLinkToDoc(peekTarget.href);
|
const maybeDoc = resolveLinkToDoc(peekTarget.href);
|
||||||
if (maybeDoc) {
|
if (maybeDoc) {
|
||||||
return {
|
return {
|
||||||
|
type: 'doc',
|
||||||
docId: maybeDoc.docId,
|
docId: maybeDoc.docId,
|
||||||
blockId: maybeDoc.blockId,
|
blockId: maybeDoc.blockId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if ('docId' in peekTarget) {
|
} else if ('docId' in peekTarget) {
|
||||||
return {
|
return {
|
||||||
|
type: 'doc',
|
||||||
docId: peekTarget.docId,
|
docId: peekTarget.docId,
|
||||||
blockId: peekTarget.blockId,
|
blockId: peekTarget.blockId,
|
||||||
};
|
};
|
||||||
@@ -100,6 +137,10 @@ export class PeekViewEntity extends Entity {
|
|||||||
private readonly _active$ = new LiveData<ActivePeekView | null>(null);
|
private readonly _active$ = new LiveData<ActivePeekView | null>(null);
|
||||||
private readonly _show$ = new LiveData<boolean>(false);
|
private readonly _show$ = new LiveData<boolean>(false);
|
||||||
|
|
||||||
|
constructor(private readonly workbenchService: WorkbenchService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
active$ = this._active$.distinctUntilChanged();
|
active$ = this._active$.distinctUntilChanged();
|
||||||
show$ = this._show$
|
show$ = this._show$
|
||||||
.map(show => show && this._active$.value !== null)
|
.map(show => show && this._active$.value !== null)
|
||||||
@@ -110,11 +151,20 @@ export class PeekViewEntity extends Entity {
|
|||||||
target: ActivePeekView['target'],
|
target: ActivePeekView['target'],
|
||||||
template?: TemplateResult
|
template?: TemplateResult
|
||||||
) => {
|
) => {
|
||||||
const resolvedInfo = resolvePeekInfoFromPeekTarget(target);
|
const resolvedInfo = resolvePeekInfoFromPeekTarget(target, template);
|
||||||
if (!resolvedInfo && !template) {
|
if (!resolvedInfo) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._active$.next({ target, info: resolvedInfo, template });
|
|
||||||
|
const active = this._active$.value;
|
||||||
|
|
||||||
|
// if there is an active peek view and it is a doc peek view, we will navigate it first
|
||||||
|
if (active?.info.type === 'doc' && this.show$.value) {
|
||||||
|
// TODO(@pengx17): scroll to the viewing position?
|
||||||
|
this.workbenchService.workbench.openPage(active.info.docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._active$.next({ target, info: resolvedInfo });
|
||||||
this._show$.next(true);
|
this._show$.next(true);
|
||||||
return firstValueFrom(race(this._active$, this.show$).pipe(map(() => {})));
|
return firstValueFrom(race(this._active$, this.show$).pipe(map(() => {})));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import type { Framework } from '@toeverything/infra';
|
import { type Framework, WorkspaceScope } from '@toeverything/infra';
|
||||||
|
|
||||||
|
import { WorkbenchService } from '../workbench';
|
||||||
import { PeekViewEntity } from './entities/peek-view';
|
import { PeekViewEntity } from './entities/peek-view';
|
||||||
import { PeekViewService } from './services/peek-view';
|
import { PeekViewService } from './services/peek-view';
|
||||||
|
|
||||||
export function configurePeekViewModule(framework: Framework) {
|
export function configurePeekViewModule(framework: Framework) {
|
||||||
framework.service(PeekViewService).entity(PeekViewEntity);
|
framework
|
||||||
|
.scope(WorkspaceScope)
|
||||||
|
.service(PeekViewService)
|
||||||
|
.entity(PeekViewEntity, [WorkbenchService]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { PeekViewEntity, PeekViewService };
|
export { PeekViewEntity, PeekViewService };
|
||||||
|
|||||||
+3
-11
@@ -3,7 +3,6 @@ import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
|
|||||||
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
|
||||||
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
|
||||||
import { BlockSuiteEditor } from '@affine/core/components/blocksuite/block-suite-editor';
|
import { BlockSuiteEditor } from '@affine/core/components/blocksuite/block-suite-editor';
|
||||||
import { ImagePreviewModal } from '@affine/core/components/image-preview';
|
|
||||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
||||||
import { PageNotFound } from '@affine/core/pages/404';
|
import { PageNotFound } from '@affine/core/pages/404';
|
||||||
import { Bound, type EdgelessRootService } from '@blocksuite/blocks';
|
import { Bound, type EdgelessRootService } from '@blocksuite/blocks';
|
||||||
@@ -14,10 +13,10 @@ import { DocsService, FrameworkScope, useService } from '@toeverything/infra';
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { WorkbenchService } from '../../workbench';
|
import { WorkbenchService } from '../../../workbench';
|
||||||
import { PeekViewService } from '../services/peek-view';
|
import { PeekViewService } from '../../services/peek-view';
|
||||||
|
import { useDoc } from '../utils';
|
||||||
import * as styles from './doc-peek-view.css';
|
import * as styles from './doc-peek-view.css';
|
||||||
import { useDoc } from './utils';
|
|
||||||
|
|
||||||
function fitViewport(
|
function fitViewport(
|
||||||
editor: AffineEditorContainer,
|
editor: AffineEditorContainer,
|
||||||
@@ -160,13 +159,6 @@ export function DocPeekPreview({
|
|||||||
defaultSelectedBlockId={blockId}
|
defaultSelectedBlockId={blockId}
|
||||||
page={doc.blockSuiteDoc}
|
page={doc.blockSuiteDoc}
|
||||||
/>
|
/>
|
||||||
{editor?.host ? (
|
|
||||||
<ImagePreviewModal
|
|
||||||
pageId={doc.id}
|
|
||||||
docCollection={doc.blockSuiteDoc.collection}
|
|
||||||
host={editor.host}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</FrameworkScope>
|
</FrameworkScope>
|
||||||
</Scrollable.Viewport>
|
</Scrollable.Viewport>
|
||||||
<Scrollable.Scrollbar />
|
<Scrollable.Scrollbar />
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { DocPeekPreview } from './doc-peek-view';
|
||||||
+89
-130
@@ -2,7 +2,6 @@ import { toast } from '@affine/component';
|
|||||||
import { Button, IconButton } from '@affine/component/ui/button';
|
import { Button, IconButton } from '@affine/component/ui/button';
|
||||||
import { Tooltip } from '@affine/component/ui/tooltip';
|
import { Tooltip } from '@affine/component/ui/tooltip';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
import { PeekViewModalContainer } from '@affine/core/modules/peek-view/view/modal-container';
|
|
||||||
import type { ImageBlockModel } from '@blocksuite/blocks';
|
import type { ImageBlockModel } from '@blocksuite/blocks';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import {
|
import {
|
||||||
@@ -16,7 +15,8 @@ import {
|
|||||||
PlusIcon,
|
PlusIcon,
|
||||||
ViewBarIcon,
|
ViewBarIcon,
|
||||||
} from '@blocksuite/icons/rc';
|
} from '@blocksuite/icons/rc';
|
||||||
import type { BlockModel, DocCollection } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
import { useService } from '@toeverything/infra';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useErrorBoundary } from 'foxact/use-error-boundary';
|
import { useErrorBoundary } from 'foxact/use-error-boundary';
|
||||||
import type { PropsWithChildren, ReactElement } from 'react';
|
import type { PropsWithChildren, ReactElement } from 'react';
|
||||||
@@ -24,7 +24,6 @@ import {
|
|||||||
Suspense,
|
Suspense,
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useLayoutEffect,
|
|
||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
@@ -33,6 +32,8 @@ import type { FallbackProps } from 'react-error-boundary';
|
|||||||
import { ErrorBoundary } from 'react-error-boundary';
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
|
import { PeekViewService } from '../../services/peek-view';
|
||||||
|
import { useDoc } from '../utils';
|
||||||
import { useZoomControls } from './hooks/use-zoom';
|
import { useZoomControls } from './hooks/use-zoom';
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
@@ -120,9 +121,8 @@ async function saveBufferToFile(url: string, filename: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ImagePreviewModalProps = {
|
export type ImagePreviewModalProps = {
|
||||||
docCollection: DocCollection;
|
docId: string;
|
||||||
pageId: string;
|
blockId: string;
|
||||||
host: HTMLElement;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ButtonWithTooltip = ({
|
const ButtonWithTooltip = ({
|
||||||
@@ -149,24 +149,25 @@ const ButtonWithTooltip = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImagePreviewModalImpl = (
|
const ImagePreviewModalImpl = ({
|
||||||
props: ImagePreviewModalProps & {
|
docId,
|
||||||
blockId: string;
|
blockId,
|
||||||
onBlockIdChange: (blockId: string | null) => void;
|
onBlockIdChange,
|
||||||
onClose: () => void;
|
onClose,
|
||||||
animating: boolean;
|
}: ImagePreviewModalProps & {
|
||||||
}
|
onBlockIdChange: (blockId: string) => void;
|
||||||
): ReactElement | null => {
|
onClose: () => void;
|
||||||
const page = useMemo(() => {
|
}): ReactElement | null => {
|
||||||
return props.docCollection.getDoc(props.pageId);
|
const { doc, workspace } = useDoc(docId);
|
||||||
}, [props.docCollection, props.pageId]);
|
const blocksuiteDoc = doc?.blockSuiteDoc;
|
||||||
|
const docCollection = workspace.docCollection;
|
||||||
const blockModel = useMemo(() => {
|
const blockModel = useMemo(() => {
|
||||||
const block = page?.getBlock(props.blockId);
|
const block = blocksuiteDoc?.getBlock(blockId);
|
||||||
if (!block) {
|
if (!block) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return block.model as ImageBlockModel;
|
return block.model as ImageBlockModel;
|
||||||
}, [page, props.blockId]);
|
}, [blockId, blocksuiteDoc]);
|
||||||
const caption = useMemo(() => {
|
const caption = useMemo(() => {
|
||||||
return blockModel?.caption ?? '';
|
return blockModel?.caption ?? '';
|
||||||
}, [blockModel?.caption]);
|
}, [blockModel?.caption]);
|
||||||
@@ -188,8 +189,7 @@ const ImagePreviewModalImpl = (
|
|||||||
|
|
||||||
const goto = useCallback(
|
const goto = useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
const workspace = props.docCollection;
|
const page = docCollection.getDoc(docId);
|
||||||
const page = workspace.getDoc(props.pageId);
|
|
||||||
assertExists(page);
|
assertExists(page);
|
||||||
|
|
||||||
const block = blocks[index];
|
const block = blocks[index];
|
||||||
@@ -197,18 +197,17 @@ const ImagePreviewModalImpl = (
|
|||||||
if (!block) return;
|
if (!block) return;
|
||||||
|
|
||||||
setCursor(index);
|
setCursor(index);
|
||||||
props.onBlockIdChange(block.id);
|
onBlockIdChange(block.id);
|
||||||
resetZoom();
|
resetZoom();
|
||||||
},
|
},
|
||||||
[props, blocks, resetZoom]
|
[docCollection, docId, blocks, onBlockIdChange, resetZoom]
|
||||||
);
|
);
|
||||||
|
|
||||||
const deleteHandler = useCallback(
|
const deleteHandler = useCallback(
|
||||||
(index: number) => {
|
(index: number) => {
|
||||||
const { pageId, docCollection: workspace, onClose } = props;
|
if (!blocksuiteDoc) {
|
||||||
|
return;
|
||||||
const page = workspace.getDoc(pageId);
|
}
|
||||||
assertExists(page);
|
|
||||||
|
|
||||||
let block = blocks[index];
|
let block = blocks[index];
|
||||||
|
|
||||||
@@ -216,7 +215,7 @@ const ImagePreviewModalImpl = (
|
|||||||
const newBlocks = blocks.toSpliced(index, 1);
|
const newBlocks = blocks.toSpliced(index, 1);
|
||||||
setBlocks(newBlocks);
|
setBlocks(newBlocks);
|
||||||
|
|
||||||
page.deleteBlock(block);
|
blocksuiteDoc.deleteBlock(block);
|
||||||
|
|
||||||
// next
|
// next
|
||||||
block = newBlocks[index];
|
block = newBlocks[index];
|
||||||
@@ -234,11 +233,11 @@ const ImagePreviewModalImpl = (
|
|||||||
setCursor(index);
|
setCursor(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
props.onBlockIdChange(block.id);
|
onBlockIdChange(block.id);
|
||||||
|
|
||||||
resetZoom();
|
resetZoom();
|
||||||
},
|
},
|
||||||
[props, blocks, setBlocks, setCursor, resetZoom]
|
[blocksuiteDoc, blocks, onBlockIdChange, resetZoom, onClose]
|
||||||
);
|
);
|
||||||
|
|
||||||
const downloadHandler = useAsyncCallback(async () => {
|
const downloadHandler = useAsyncCallback(async () => {
|
||||||
@@ -256,66 +255,58 @@ const ImagePreviewModalImpl = (
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const page = props.docCollection.getDoc(props.pageId);
|
if (!blockModel || !blocksuiteDoc) {
|
||||||
assertExists(page);
|
|
||||||
|
|
||||||
const block = page.getBlock(props.blockId);
|
|
||||||
if (!block) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blockModel = block.model as ImageBlockModel;
|
|
||||||
|
|
||||||
const prevs = page.getPrevs(blockModel).filter(filterImageBlock);
|
const prevs = blocksuiteDoc.getPrevs(blockModel).filter(filterImageBlock);
|
||||||
const nexts = page.getNexts(blockModel).filter(filterImageBlock);
|
const nexts = blocksuiteDoc.getNexts(blockModel).filter(filterImageBlock);
|
||||||
|
|
||||||
const blocks = [...prevs, blockModel, ...nexts];
|
const blocks = [...prevs, blockModel, ...nexts];
|
||||||
setBlocks(blocks);
|
setBlocks(blocks);
|
||||||
setCursor(blocks.length ? prevs.length : 0);
|
setCursor(blocks.length ? prevs.length : 0);
|
||||||
}, [props.blockId, props.pageId, props.docCollection, setBlocks]);
|
}, [setBlocks, blockModel, blocksuiteDoc]);
|
||||||
|
|
||||||
const { data, error } = useSWR(
|
const { data, error } = useSWR(['workspace', 'image', docId, blockId], {
|
||||||
['workspace', 'image', props.pageId, props.blockId],
|
fetcher: ([_, __, pageId, blockId]) => {
|
||||||
{
|
const page = docCollection.getDoc(pageId);
|
||||||
fetcher: ([_, __, pageId, blockId]) => {
|
assertExists(page);
|
||||||
const page = props.docCollection.getDoc(pageId);
|
|
||||||
assertExists(page);
|
|
||||||
|
|
||||||
const block = page.getBlock(blockId);
|
const block = page.getBlock(blockId);
|
||||||
if (!block) {
|
if (!block) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const blockModel = block.model as ImageBlockModel;
|
const blockModel = block.model as ImageBlockModel;
|
||||||
return props.docCollection.blobSync.get(blockModel.sourceId as string);
|
return docCollection.blobSync.get(blockModel.sourceId as string);
|
||||||
},
|
},
|
||||||
suspense: true,
|
suspense: true,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyUp = (event: KeyboardEvent) => {
|
const handleKeyUp = (event: KeyboardEvent) => {
|
||||||
if (!page || !blockModel) {
|
if (!blocksuiteDoc || !blockModel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'ArrowLeft') {
|
if (event.key === 'ArrowLeft') {
|
||||||
const prevBlock = page
|
const prevBlock = blocksuiteDoc
|
||||||
.getPrevs(blockModel)
|
.getPrevs(blockModel)
|
||||||
.findLast(
|
.findLast(
|
||||||
(block): block is ImageBlockModel =>
|
(block): block is ImageBlockModel =>
|
||||||
block.flavour === 'affine:image'
|
block.flavour === 'affine:image'
|
||||||
);
|
);
|
||||||
if (prevBlock) {
|
if (prevBlock) {
|
||||||
props.onBlockIdChange(prevBlock.id);
|
onBlockIdChange(prevBlock.id);
|
||||||
}
|
}
|
||||||
} else if (event.key === 'ArrowRight') {
|
} else if (event.key === 'ArrowRight') {
|
||||||
const nextBlock = page
|
const nextBlock = blocksuiteDoc
|
||||||
.getNexts(blockModel)
|
.getNexts(blockModel)
|
||||||
.find(
|
.find(
|
||||||
(block): block is ImageBlockModel =>
|
(block): block is ImageBlockModel =>
|
||||||
block.flavour === 'affine:image'
|
block.flavour === 'affine:image'
|
||||||
);
|
);
|
||||||
if (nextBlock) {
|
if (nextBlock) {
|
||||||
props.onBlockIdChange(nextBlock.id);
|
onBlockIdChange(nextBlock.id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -328,7 +319,7 @@ const ImagePreviewModalImpl = (
|
|||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keyup', handleKeyUp);
|
document.removeEventListener('keyup', handleKeyUp);
|
||||||
};
|
};
|
||||||
}, [blockModel, page, props]);
|
}, [blockModel, blocksuiteDoc, onBlockIdChange]);
|
||||||
|
|
||||||
useErrorBoundary(error);
|
useErrorBoundary(error);
|
||||||
|
|
||||||
@@ -351,8 +342,11 @@ const ImagePreviewModalImpl = (
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={styles.imagePreviewModalStyle}>
|
<div
|
||||||
<div className={styles.imagePreviewTrap} onClick={props.onClose} />
|
data-testid="image-preview-modal"
|
||||||
|
className={styles.imagePreviewModalStyle}
|
||||||
|
>
|
||||||
|
<div className={styles.imagePreviewTrap} onClick={onClose} />
|
||||||
<div className={styles.imagePreviewModalContainerStyle}>
|
<div className={styles.imagePreviewModalContainerStyle}>
|
||||||
<div
|
<div
|
||||||
className={clsx('zoom-area', { 'zoomed-bigger': isZoomedBigger })}
|
className={clsx('zoom-area', { 'zoomed-bigger': isZoomedBigger })}
|
||||||
@@ -360,7 +354,7 @@ const ImagePreviewModalImpl = (
|
|||||||
>
|
>
|
||||||
<div className={styles.imagePreviewModalCenterStyle}>
|
<div className={styles.imagePreviewModalCenterStyle}>
|
||||||
<img
|
<img
|
||||||
data-blob-id={props.blockId}
|
data-blob-id={blockId}
|
||||||
data-testid="image-content"
|
data-testid="image-content"
|
||||||
src={url}
|
src={url}
|
||||||
alt={caption}
|
alt={caption}
|
||||||
@@ -397,7 +391,7 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="previous-image-button"
|
data-testid="previous-image-button"
|
||||||
tooltip="Previous"
|
tooltip="Previous"
|
||||||
icon={<ArrowLeftSmallIcon />}
|
icon={<ArrowLeftSmallIcon />}
|
||||||
disabled={props.animating || cursor < 1}
|
disabled={cursor < 1}
|
||||||
onClick={() => goto(cursor - 1)}
|
onClick={() => goto(cursor - 1)}
|
||||||
/>
|
/>
|
||||||
<div className={styles.cursorStyle}>
|
<div className={styles.cursorStyle}>
|
||||||
@@ -407,7 +401,7 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="next-image-button"
|
data-testid="next-image-button"
|
||||||
tooltip="Next"
|
tooltip="Next"
|
||||||
icon={<ArrowRightSmallIcon />}
|
icon={<ArrowRightSmallIcon />}
|
||||||
disabled={props.animating || cursor + 1 === blocks.length}
|
disabled={cursor + 1 === blocks.length}
|
||||||
onClick={() => goto(cursor + 1)}
|
onClick={() => goto(cursor + 1)}
|
||||||
/>
|
/>
|
||||||
<div className={styles.dividerStyle}></div>
|
<div className={styles.dividerStyle}></div>
|
||||||
@@ -415,21 +409,18 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="fit-to-screen-button"
|
data-testid="fit-to-screen-button"
|
||||||
tooltip="Fit to screen"
|
tooltip="Fit to screen"
|
||||||
icon={<ViewBarIcon />}
|
icon={<ViewBarIcon />}
|
||||||
disabled={props.animating}
|
|
||||||
onClick={() => resetZoom()}
|
onClick={() => resetZoom()}
|
||||||
/>
|
/>
|
||||||
<ButtonWithTooltip
|
<ButtonWithTooltip
|
||||||
data-testid="zoom-out-button"
|
data-testid="zoom-out-button"
|
||||||
tooltip="Zoom out"
|
tooltip="Zoom out"
|
||||||
icon={<MinusIcon />}
|
icon={<MinusIcon />}
|
||||||
disabled={props.animating}
|
|
||||||
onClick={zoomOut}
|
onClick={zoomOut}
|
||||||
/>
|
/>
|
||||||
<ButtonWithTooltip
|
<ButtonWithTooltip
|
||||||
data-testid="reset-scale-button"
|
data-testid="reset-scale-button"
|
||||||
tooltip="Reset scale"
|
tooltip="Reset scale"
|
||||||
onClick={resetScale}
|
onClick={resetScale}
|
||||||
disabled={props.animating}
|
|
||||||
>
|
>
|
||||||
{`${(currentScale * 100).toFixed(0)}%`}
|
{`${(currentScale * 100).toFixed(0)}%`}
|
||||||
</ButtonWithTooltip>
|
</ButtonWithTooltip>
|
||||||
@@ -438,7 +429,6 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="zoom-in-button"
|
data-testid="zoom-in-button"
|
||||||
tooltip="Zoom in"
|
tooltip="Zoom in"
|
||||||
icon={<PlusIcon />}
|
icon={<PlusIcon />}
|
||||||
disabled={props.animating}
|
|
||||||
onClick={zoomIn}
|
onClick={zoomIn}
|
||||||
/>
|
/>
|
||||||
<div className={styles.dividerStyle}></div>
|
<div className={styles.dividerStyle}></div>
|
||||||
@@ -446,14 +436,12 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="download-button"
|
data-testid="download-button"
|
||||||
tooltip="Download"
|
tooltip="Download"
|
||||||
icon={<DownloadIcon />}
|
icon={<DownloadIcon />}
|
||||||
disabled={props.animating}
|
|
||||||
onClick={downloadHandler}
|
onClick={downloadHandler}
|
||||||
/>
|
/>
|
||||||
<ButtonWithTooltip
|
<ButtonWithTooltip
|
||||||
data-testid="copy-to-clipboard-button"
|
data-testid="copy-to-clipboard-button"
|
||||||
tooltip="Copy to clipboard"
|
tooltip="Copy to clipboard"
|
||||||
icon={<CopyIcon />}
|
icon={<CopyIcon />}
|
||||||
disabled={props.animating}
|
|
||||||
onClick={copyHandler}
|
onClick={copyHandler}
|
||||||
/>
|
/>
|
||||||
<div className={styles.dividerStyle}></div>
|
<div className={styles.dividerStyle}></div>
|
||||||
@@ -461,7 +449,7 @@ const ImagePreviewModalImpl = (
|
|||||||
data-testid="delete-button"
|
data-testid="delete-button"
|
||||||
tooltip="Delete"
|
tooltip="Delete"
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
disabled={props.animating || blocks.length === 0}
|
disabled={blocks.length === 0}
|
||||||
onClick={() => deleteHandler(cursor)}
|
onClick={() => deleteHandler(cursor)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -483,67 +471,38 @@ export const ImagePreviewErrorBoundary = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ImagePreviewModal = (
|
export const ImagePreviewPeekView = (
|
||||||
props: ImagePreviewModalProps
|
props: ImagePreviewModalProps
|
||||||
): ReactElement | null => {
|
): ReactElement | null => {
|
||||||
const [show, setShow] = useState(false);
|
const [blockId, setBlockId] = useState<string | null>(props.blockId);
|
||||||
const [blockId, setBlockId] = useState<string | null>(null);
|
const peekView = useService(PeekViewService).peekView;
|
||||||
const isOpen = show && !!blockId;
|
const onClose = peekView.close;
|
||||||
|
const buttonRef = useRef<HTMLButtonElement | null>(null);
|
||||||
|
|
||||||
// todo: refactor this to use peek view service
|
useEffect(() => {
|
||||||
useLayoutEffect(() => {
|
setBlockId(props.blockId);
|
||||||
const handleDblClick = (event: MouseEvent) => {
|
}, [props.blockId]);
|
||||||
const target = event.target as HTMLElement | null;
|
|
||||||
if (target?.tagName === 'IMG') {
|
|
||||||
const imageBlock = target.closest('affine-image');
|
|
||||||
if (imageBlock) {
|
|
||||||
const blockId = imageBlock.dataset.blockId;
|
|
||||||
if (!blockId) return;
|
|
||||||
setBlockId(blockId);
|
|
||||||
setShow(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
props.host.addEventListener('dblclick', handleDblClick);
|
|
||||||
return () => {
|
|
||||||
props.host.removeEventListener('dblclick', handleDblClick);
|
|
||||||
};
|
|
||||||
}, [props.host]);
|
|
||||||
|
|
||||||
const [animating, setAnimating] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PeekViewModalContainer
|
<ImagePreviewErrorBoundary>
|
||||||
padding={false}
|
<Suspense>
|
||||||
onOpenChange={setShow}
|
{blockId ? (
|
||||||
open={isOpen}
|
<ImagePreviewModalImpl
|
||||||
animation="fade"
|
{...props}
|
||||||
onAnimationStart={() => setAnimating(true)}
|
onClose={onClose}
|
||||||
onAnimateEnd={() => setAnimating(false)}
|
blockId={blockId}
|
||||||
testId="image-preview-modal"
|
onBlockIdChange={setBlockId}
|
||||||
>
|
/>
|
||||||
<ImagePreviewErrorBoundary>
|
) : null}
|
||||||
<Suspense>
|
<button
|
||||||
{blockId ? (
|
ref={buttonRef}
|
||||||
<ImagePreviewModalImpl
|
data-testid="image-preview-close-button"
|
||||||
{...props}
|
onClick={onClose}
|
||||||
animating={animating}
|
className={styles.imagePreviewModalCloseButtonStyle}
|
||||||
blockId={blockId}
|
>
|
||||||
onBlockIdChange={setBlockId}
|
<CloseIcon />
|
||||||
onClose={() => setShow(false)}
|
</button>
|
||||||
/>
|
</Suspense>
|
||||||
) : null}
|
</ImagePreviewErrorBoundary>
|
||||||
<button
|
|
||||||
data-testid="image-preview-close-button"
|
|
||||||
onClick={() => {
|
|
||||||
setShow(false);
|
|
||||||
}}
|
|
||||||
className={styles.imagePreviewModalCloseButtonStyle}
|
|
||||||
>
|
|
||||||
<CloseIcon />
|
|
||||||
</button>
|
|
||||||
</Suspense>
|
|
||||||
</ImagePreviewErrorBoundary>
|
|
||||||
</PeekViewModalContainer>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -150,6 +150,11 @@ export const modalContent = style({
|
|||||||
// :focus-visible will set outline
|
// :focus-visible will set outline
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
selectors: {
|
||||||
|
'&[data-no-interaction=true]': {
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const modalControls = style({
|
export const modalControls = style({
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { assignInlineVars } from '@vanilla-extract/dynamic';
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
|
forwardRef,
|
||||||
type PropsWithChildren,
|
type PropsWithChildren,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
@@ -57,30 +58,38 @@ function getElementScreenPositionCenter(target: HTMLElement) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PeekViewModalContainer = ({
|
export type PeekViewModalContainerProps = PropsWithChildren<{
|
||||||
onOpenChange,
|
|
||||||
open,
|
|
||||||
target,
|
|
||||||
controls,
|
|
||||||
children,
|
|
||||||
hideOnEntering,
|
|
||||||
onAnimationStart,
|
|
||||||
onAnimateEnd,
|
|
||||||
animation = 'zoom',
|
|
||||||
padding = true,
|
|
||||||
testId,
|
|
||||||
}: PropsWithChildren<{
|
|
||||||
open: boolean;
|
|
||||||
hideOnEntering?: boolean;
|
|
||||||
target?: HTMLElement;
|
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
|
open: boolean;
|
||||||
|
target?: HTMLElement;
|
||||||
controls?: React.ReactNode;
|
controls?: React.ReactNode;
|
||||||
|
hideOnEntering?: boolean;
|
||||||
onAnimationStart?: () => void;
|
onAnimationStart?: () => void;
|
||||||
onAnimateEnd?: () => void;
|
onAnimateEnd?: () => void;
|
||||||
padding?: boolean;
|
padding?: boolean;
|
||||||
animation?: 'fade' | 'zoom';
|
animation?: 'fade' | 'zoom';
|
||||||
testId?: string;
|
testId?: string;
|
||||||
}>) => {
|
}>;
|
||||||
|
|
||||||
|
export const PeekViewModalContainer = forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
PeekViewModalContainerProps
|
||||||
|
>(function PeekViewModalContainer(
|
||||||
|
{
|
||||||
|
onOpenChange,
|
||||||
|
open,
|
||||||
|
target,
|
||||||
|
controls,
|
||||||
|
children,
|
||||||
|
hideOnEntering,
|
||||||
|
onAnimationStart,
|
||||||
|
onAnimateEnd,
|
||||||
|
animation = 'zoom',
|
||||||
|
padding = true,
|
||||||
|
testId,
|
||||||
|
},
|
||||||
|
ref
|
||||||
|
) {
|
||||||
const [{ status }, toggle] = useTransition({
|
const [{ status }, toggle] = useTransition({
|
||||||
timeout: animationTimeout,
|
timeout: animationTimeout,
|
||||||
});
|
});
|
||||||
@@ -112,6 +121,7 @@ export const PeekViewModalContainer = ({
|
|||||||
onAnimationEnd={onAnimateEnd}
|
onAnimationEnd={onAnimateEnd}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
ref={ref}
|
||||||
data-testid={testId}
|
data-testid={testId}
|
||||||
data-peek-view-wrapper
|
data-peek-view-wrapper
|
||||||
className={styles.modalContentWrapper}
|
className={styles.modalContentWrapper}
|
||||||
@@ -133,6 +143,7 @@ export const PeekViewModalContainer = ({
|
|||||||
>
|
>
|
||||||
<Dialog.Content
|
<Dialog.Content
|
||||||
{...contentOptions}
|
{...contentOptions}
|
||||||
|
data-no-interaction={status !== 'entered'}
|
||||||
className={styles.modalContent}
|
className={styles.modalContent}
|
||||||
>
|
>
|
||||||
{hideOnEntering && status === 'entering' ? null : children}
|
{hideOnEntering && status === 'entering' ? null : children}
|
||||||
@@ -148,4 +159,4 @@ export const PeekViewModalContainer = ({
|
|||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
</PeekViewContext.Provider>
|
</PeekViewContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|||||||
@@ -5,34 +5,41 @@ import { useEffect, useMemo } from 'react';
|
|||||||
|
|
||||||
import type { ActivePeekView } from '../entities/peek-view';
|
import type { ActivePeekView } from '../entities/peek-view';
|
||||||
import { PeekViewService } from '../services/peek-view';
|
import { PeekViewService } from '../services/peek-view';
|
||||||
import { DocPeekPreview } from './doc-peek-view';
|
import { DocPeekPreview } from './doc-preview';
|
||||||
import { PeekViewModalContainer } from './modal-container';
|
import { ImagePreviewPeekView } from './image-preview';
|
||||||
|
import {
|
||||||
|
PeekViewModalContainer,
|
||||||
|
type PeekViewModalContainerProps,
|
||||||
|
} from './modal-container';
|
||||||
import {
|
import {
|
||||||
DefaultPeekViewControls,
|
DefaultPeekViewControls,
|
||||||
DocPeekViewControls,
|
DocPeekViewControls,
|
||||||
} from './peek-view-controls';
|
} from './peek-view-controls';
|
||||||
|
|
||||||
function renderPeekView({ info, template }: ActivePeekView) {
|
function renderPeekView({ info }: ActivePeekView) {
|
||||||
if (template) {
|
if (info.type === 'template') {
|
||||||
return toReactNode(template);
|
return toReactNode(info.template);
|
||||||
|
}
|
||||||
|
if (info.type === 'doc') {
|
||||||
|
return (
|
||||||
|
<DocPeekPreview
|
||||||
|
mode={info.mode}
|
||||||
|
xywh={info.xywh}
|
||||||
|
docId={info.docId}
|
||||||
|
blockId={info.blockId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info) {
|
if (info.type === 'image') {
|
||||||
return null;
|
return <ImagePreviewPeekView docId={info.docId} blockId={info.blockId} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return null; // unreachable
|
||||||
<DocPeekPreview
|
|
||||||
mode={info.mode}
|
|
||||||
xywh={info.xywh}
|
|
||||||
docId={info.docId}
|
|
||||||
blockId={info.blockId}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderControls = ({ info }: ActivePeekView) => {
|
const renderControls = ({ info }: ActivePeekView) => {
|
||||||
if (info && 'docId' in info) {
|
if (info.type === 'doc') {
|
||||||
return (
|
return (
|
||||||
<DocPeekViewControls
|
<DocPeekViewControls
|
||||||
mode={info.mode}
|
mode={info.mode}
|
||||||
@@ -42,20 +49,44 @@ const renderControls = ({ info }: ActivePeekView) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info.type === 'image') {
|
||||||
|
return null; // image controls are rendered in the image preview
|
||||||
|
}
|
||||||
|
|
||||||
return <DefaultPeekViewControls />;
|
return <DefaultPeekViewControls />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getRendererProps = (
|
||||||
|
activePeekView?: ActivePeekView
|
||||||
|
): Partial<PeekViewModalContainerProps> | undefined => {
|
||||||
|
if (!activePeekView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const preview = renderPeekView(activePeekView);
|
||||||
|
const controls = renderControls(activePeekView);
|
||||||
|
return {
|
||||||
|
children: preview,
|
||||||
|
controls,
|
||||||
|
target:
|
||||||
|
activePeekView?.target instanceof HTMLElement
|
||||||
|
? activePeekView.target
|
||||||
|
: undefined,
|
||||||
|
padding: activePeekView.info.type === 'doc',
|
||||||
|
animation: activePeekView.info.type === 'image' ? 'fade' : 'zoom',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const PeekViewManagerModal = () => {
|
export const PeekViewManagerModal = () => {
|
||||||
const peekViewEntity = useService(PeekViewService).peekView;
|
const peekViewEntity = useService(PeekViewService).peekView;
|
||||||
const activePeekView = useLiveData(peekViewEntity.active$);
|
const activePeekView = useLiveData(peekViewEntity.active$);
|
||||||
const show = useLiveData(peekViewEntity.show$);
|
const show = useLiveData(peekViewEntity.show$);
|
||||||
|
|
||||||
const preview = useMemo(() => {
|
const renderProps = useMemo(() => {
|
||||||
return activePeekView ? renderPeekView(activePeekView) : null;
|
if (!activePeekView) {
|
||||||
}, [activePeekView]);
|
return;
|
||||||
|
}
|
||||||
const controls = useMemo(() => {
|
return getRendererProps(activePeekView);
|
||||||
return activePeekView ? renderControls(activePeekView) : null;
|
|
||||||
}, [activePeekView]);
|
}, [activePeekView]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -72,20 +103,15 @@ export const PeekViewManagerModal = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PeekViewModalContainer
|
<PeekViewModalContainer
|
||||||
open={show && !!preview}
|
{...renderProps}
|
||||||
target={
|
open={show && !!renderProps}
|
||||||
activePeekView?.target instanceof HTMLElement
|
|
||||||
? activePeekView.target
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
controls={controls}
|
|
||||||
onOpenChange={open => {
|
onOpenChange={open => {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
peekViewEntity.close();
|
peekViewEntity.close();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{preview}
|
{renderProps?.children}
|
||||||
</PeekViewModalContainer>
|
</PeekViewModalContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import type { Map as YMap } from 'yjs';
|
|||||||
|
|
||||||
import { AffineErrorBoundary } from '../../../components/affine/affine-error-boundary';
|
import { AffineErrorBoundary } from '../../../components/affine/affine-error-boundary';
|
||||||
import { GlobalPageHistoryModal } from '../../../components/affine/page-history-modal';
|
import { GlobalPageHistoryModal } from '../../../components/affine/page-history-modal';
|
||||||
import { ImagePreviewModal } from '../../../components/image-preview';
|
|
||||||
import { PageDetailEditor } from '../../../components/page-detail-editor';
|
import { PageDetailEditor } from '../../../components/page-detail-editor';
|
||||||
import { TrashPageFooter } from '../../../components/pure/trash-page-footer';
|
import { TrashPageFooter } from '../../../components/pure/trash-page-footer';
|
||||||
import { TopTip } from '../../../components/top-tip';
|
import { TopTip } from '../../../components/top-tip';
|
||||||
@@ -311,14 +310,6 @@ const DetailPageImpl = memo(function DetailPageImpl() {
|
|||||||
</MultiTabSidebarBody>
|
</MultiTabSidebarBody>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{editor?.host ? (
|
|
||||||
<ImagePreviewModal
|
|
||||||
pageId={doc.id}
|
|
||||||
docCollection={docCollection}
|
|
||||||
host={editor.host}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<GlobalPageHistoryModal />
|
<GlobalPageHistoryModal />
|
||||||
<PageAIOnboarding />
|
<PageAIOnboarding />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
"@affine/env": "workspace:*",
|
"@affine/env": "workspace:*",
|
||||||
"@affine/i18n": "workspace:*",
|
"@affine/i18n": "workspace:*",
|
||||||
"@affine/native": "workspace:*",
|
"@affine/native": "workspace:*",
|
||||||
"@blocksuite/block-std": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/block-std": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/blocks": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/blocks": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/presets": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/presets": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@blocksuite/store": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/store": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@electron-forge/cli": "^7.3.0",
|
"@electron-forge/cli": "^7.3.0",
|
||||||
"@electron-forge/core": "^7.3.0",
|
"@electron-forge/core": "^7.3.0",
|
||||||
"@electron-forge/core-utils": "^7.3.0",
|
"@electron-forge/core-utils": "^7.3.0",
|
||||||
|
|||||||
@@ -38,11 +38,7 @@ async function importImage(page: Page, url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function closeImagePreviewModal(page: Page) {
|
async function closeImagePreviewModal(page: Page) {
|
||||||
await page
|
await page.getByTestId('image-preview-close-button').first().click();
|
||||||
.getByTestId('image-preview-modal')
|
|
||||||
.getByTestId('image-preview-close-button')
|
|
||||||
.first()
|
|
||||||
.click();
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"@affine/env": "workspace:*",
|
"@affine/env": "workspace:*",
|
||||||
"@affine/templates": "workspace:*",
|
"@affine/templates": "workspace:*",
|
||||||
"@aws-sdk/client-s3": "3.592.0",
|
"@aws-sdk/client-s3": "3.592.0",
|
||||||
"@blocksuite/presets": "0.15.0-canary-202406252341-172c4b8",
|
"@blocksuite/presets": "0.15.0-canary-202406260417-3b9fb16",
|
||||||
"@clack/core": "^0.3.4",
|
"@clack/core": "^0.3.4",
|
||||||
"@clack/prompts": "^0.7.0",
|
"@clack/prompts": "^0.7.0",
|
||||||
"@magic-works/i18n-codegen": "^0.6.0",
|
"@magic-works/i18n-codegen": "^0.6.0",
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ __metadata:
|
|||||||
"@affine/env": "workspace:*"
|
"@affine/env": "workspace:*"
|
||||||
"@affine/templates": "workspace:*"
|
"@affine/templates": "workspace:*"
|
||||||
"@aws-sdk/client-s3": "npm:3.592.0"
|
"@aws-sdk/client-s3": "npm:3.592.0"
|
||||||
"@blocksuite/presets": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/presets": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@clack/core": "npm:^0.3.4"
|
"@clack/core": "npm:^0.3.4"
|
||||||
"@clack/prompts": "npm:^0.7.0"
|
"@clack/prompts": "npm:^0.7.0"
|
||||||
"@magic-works/i18n-codegen": "npm:^0.6.0"
|
"@magic-works/i18n-codegen": "npm:^0.6.0"
|
||||||
@@ -282,12 +282,12 @@ __metadata:
|
|||||||
"@affine/electron-api": "workspace:*"
|
"@affine/electron-api": "workspace:*"
|
||||||
"@affine/graphql": "workspace:*"
|
"@affine/graphql": "workspace:*"
|
||||||
"@affine/i18n": "workspace:*"
|
"@affine/i18n": "workspace:*"
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/blocks": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/blocks": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/icons": "npm:2.1.58"
|
"@blocksuite/icons": "npm:2.1.58"
|
||||||
"@blocksuite/presets": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/presets": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@dnd-kit/core": "npm:^6.1.0"
|
"@dnd-kit/core": "npm:^6.1.0"
|
||||||
"@dnd-kit/modifiers": "npm:^7.0.0"
|
"@dnd-kit/modifiers": "npm:^7.0.0"
|
||||||
"@dnd-kit/sortable": "npm:^8.0.0"
|
"@dnd-kit/sortable": "npm:^8.0.0"
|
||||||
@@ -383,13 +383,13 @@ __metadata:
|
|||||||
"@affine/graphql": "workspace:*"
|
"@affine/graphql": "workspace:*"
|
||||||
"@affine/i18n": "workspace:*"
|
"@affine/i18n": "workspace:*"
|
||||||
"@affine/templates": "workspace:*"
|
"@affine/templates": "workspace:*"
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/blocks": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/blocks": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/icons": "npm:2.1.58"
|
"@blocksuite/icons": "npm:2.1.58"
|
||||||
"@blocksuite/inline": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/inline": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/presets": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/presets": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@dnd-kit/core": "npm:^6.1.0"
|
"@dnd-kit/core": "npm:^6.1.0"
|
||||||
"@dnd-kit/modifiers": "npm:^7.0.0"
|
"@dnd-kit/modifiers": "npm:^7.0.0"
|
||||||
"@dnd-kit/sortable": "npm:^8.0.0"
|
"@dnd-kit/sortable": "npm:^8.0.0"
|
||||||
@@ -514,10 +514,10 @@ __metadata:
|
|||||||
"@affine/env": "workspace:*"
|
"@affine/env": "workspace:*"
|
||||||
"@affine/i18n": "workspace:*"
|
"@affine/i18n": "workspace:*"
|
||||||
"@affine/native": "workspace:*"
|
"@affine/native": "workspace:*"
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/blocks": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/blocks": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/presets": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/presets": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@electron-forge/cli": "npm:^7.3.0"
|
"@electron-forge/cli": "npm:^7.3.0"
|
||||||
"@electron-forge/core": "npm:^7.3.0"
|
"@electron-forge/core": "npm:^7.3.0"
|
||||||
"@electron-forge/core-utils": "npm:^7.3.0"
|
"@electron-forge/core-utils": "npm:^7.3.0"
|
||||||
@@ -573,8 +573,8 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@affine/env@workspace:packages/common/env"
|
resolution: "@affine/env@workspace:packages/common/env"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
lit: "npm:^3.1.2"
|
lit: "npm:^3.1.2"
|
||||||
react: "npm:18.3.1"
|
react: "npm:18.3.1"
|
||||||
react-dom: "npm:18.3.1"
|
react-dom: "npm:18.3.1"
|
||||||
@@ -4105,30 +4105,30 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/block-std@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/block-std@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/block-std@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/block-std@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
lit: "npm:^3.1.3"
|
lit: "npm:^3.1.3"
|
||||||
lz-string: "npm:^1.5.0"
|
lz-string: "npm:^1.5.0"
|
||||||
w3c-keyname: "npm:^2.2.8"
|
w3c-keyname: "npm:^2.2.8"
|
||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@blocksuite/inline": 0.15.0-canary-202406252341-172c4b8
|
"@blocksuite/inline": 0.15.0-canary-202406260417-3b9fb16
|
||||||
"@blocksuite/store": 0.15.0-canary-202406252341-172c4b8
|
"@blocksuite/store": 0.15.0-canary-202406260417-3b9fb16
|
||||||
checksum: 10/b3019cd56ac99e3474929a2a6bd9959035dc1901d4e6ab2c3e9911fd8ead94ba0b6025b8fa88d9987f5731c7f331e539e4402a3a0188531d77ae57f0df928d5c
|
checksum: 10/5f39220f61a25205740097265610ee87faf6285a8ad6b1a0959ddfebda5c13df6d23de87af2e5d497c5e805ca546b0030328918e8ec7c8052721cdc72d44a547
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/blocks@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/blocks@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/blocks@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/blocks@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/inline": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/inline": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@dotlottie/player-component": "npm:^2.7.12"
|
"@dotlottie/player-component": "npm:^2.7.12"
|
||||||
"@floating-ui/dom": "npm:^1.6.5"
|
"@floating-ui/dom": "npm:^1.6.5"
|
||||||
"@lit/context": "npm:^1.1.1"
|
"@lit/context": "npm:^1.1.1"
|
||||||
@@ -4165,17 +4165,17 @@ __metadata:
|
|||||||
sortablejs: "npm:^1.15.2"
|
sortablejs: "npm:^1.15.2"
|
||||||
unified: "npm:^11.0.4"
|
unified: "npm:^11.0.4"
|
||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
checksum: 10/4a35f9ecf79be53cafd53c197b8f1335f2615e91f68b417473a8681e5c57bc0c62954eb1a5925c0e49899144dd6a95b10900ef0bdbae1709fc20118797f09b58
|
checksum: 10/e96521e726df32722c044be42355a3161251afb1ef77e19396fe20d5593b05e3a6a54bb57791c80521b43078d5573374286a6b7f0874f75f9f7a2dd5c9741dee
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/global@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/global@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/global@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/global@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
lib0: "npm:^0.2.94"
|
lib0: "npm:^0.2.94"
|
||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
checksum: 10/e4804b03a03fbd019616c54729563f2fd087d302034529829a1ad7dd8343ac405ee18776cd3f36409e447e4f07b7a8b7099d915af5fb834db21d7be4e0eb3f08
|
checksum: 10/2d4717ef757045ae494df389b78548d873accd294d8ae9742e789a4e759cda3c180bad2063015b8d804d5120c1ee6910ad3409dcf68347a001742a5d0a452452
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -4195,45 +4195,45 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/inline@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/inline@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/inline@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/inline@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
lit: ^3.1.1
|
lit: ^3.1.1
|
||||||
yjs: ^13.6.15
|
yjs: ^13.6.15
|
||||||
checksum: 10/766524a5c923bc2be852763173042d59bd1dbe7736c37fb096a23bab580fa2baa85e768333f72ccdf3d362ba91ec19cff0cda4a8ef072489581cbf846859bc38
|
checksum: 10/8c4387116ddc3f65408cc15b4ef1e63f089d8b18891ac79a78c8707c6e88c0d8d6017768c38877e38e73d977f7ca4618d8fe09da8b9cc5e429273dbcd066e176
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/presets@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/presets@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/presets@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/presets@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/blocks": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/blocks": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/inline": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/inline": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@dotlottie/player-component": "npm:^2.7.12"
|
"@dotlottie/player-component": "npm:^2.7.12"
|
||||||
"@fal-ai/serverless-client": "npm:^0.10.0"
|
"@fal-ai/serverless-client": "npm:^0.10.0"
|
||||||
"@floating-ui/dom": "npm:^1.6.5"
|
"@floating-ui/dom": "npm:^1.6.5"
|
||||||
"@toeverything/theme": "npm:^0.7.32"
|
"@toeverything/theme": "npm:^0.7.32"
|
||||||
lit: "npm:^3.1.3"
|
lit: "npm:^3.1.3"
|
||||||
openai: "npm:^4.47.2"
|
openai: "npm:^4.47.2"
|
||||||
checksum: 10/f15f9cf8293c132df0cf48b83021a328a45a29e8426a2ab28878e18e80e23aebd1d3c8a8429af49df97c3c178bb71be47a15cf2559672ff6de901508a599324d
|
checksum: 10/7ca99e06c13edbb2585dbc2fc79a2f3f231e17698d361407f4921947cf460efaac8eb63c8c28817d085507139171ebb6179b2fb781dba648785337aba07728e3
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/store@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/store@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/store@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/store@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/inline": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/inline": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/sync": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/sync": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@types/flexsearch": "npm:^0.7.6"
|
"@types/flexsearch": "npm:^0.7.6"
|
||||||
flexsearch: "npm:0.7.43"
|
flexsearch: "npm:0.7.43"
|
||||||
lib0: "npm:^0.2.94"
|
lib0: "npm:^0.2.94"
|
||||||
@@ -4244,21 +4244,21 @@ __metadata:
|
|||||||
zod: "npm:^3.23.8"
|
zod: "npm:^3.23.8"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
yjs: ^13.6.15
|
yjs: ^13.6.15
|
||||||
checksum: 10/fc63b49298debf3afbbed25e0671418ea2b0e1963f955c2ca51d7f8f86994b7ff83fbbbb1e89a78eb2c9e5643ecbd27f1e1565a13ba3d9dd5710a1efb0132755
|
checksum: 10/7e5aa60619d6cac4619d390391d190c2401e47d12cc7df5db315e492a2fda701aa93aa791bcef8bf73fdfc9180d54f0bb1d007b81755f0c12f29d0379827fa77
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@blocksuite/sync@npm:0.15.0-canary-202406252341-172c4b8":
|
"@blocksuite/sync@npm:0.15.0-canary-202406260417-3b9fb16":
|
||||||
version: 0.15.0-canary-202406252341-172c4b8
|
version: 0.15.0-canary-202406260417-3b9fb16
|
||||||
resolution: "@blocksuite/sync@npm:0.15.0-canary-202406252341-172c4b8"
|
resolution: "@blocksuite/sync@npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
idb: "npm:^8.0.0"
|
idb: "npm:^8.0.0"
|
||||||
idb-keyval: "npm:^6.2.1"
|
idb-keyval: "npm:^6.2.1"
|
||||||
y-protocols: "npm:^1.0.6"
|
y-protocols: "npm:^1.0.6"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
yjs: ^13.6.15
|
yjs: ^13.6.15
|
||||||
checksum: 10/22a320983945d14f28fdd83baf219e8a2e3b37ead6556cff58557b1822b3f84ec841e6c1373cf62ae536923d45baea007c6e155839fbde5539105304aeb7da83
|
checksum: 10/f1493bf7d54e1ea2990ba6898c4df0cc3fb2f193e81281bf3fbbe0093e6252e655d69b3af059a09a6f35180490d2291beb25b2f7e9d0208b1fd0e7b509504c2f
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -15649,11 +15649,11 @@ __metadata:
|
|||||||
"@affine/debug": "workspace:*"
|
"@affine/debug": "workspace:*"
|
||||||
"@affine/env": "workspace:*"
|
"@affine/env": "workspace:*"
|
||||||
"@affine/templates": "workspace:*"
|
"@affine/templates": "workspace:*"
|
||||||
"@blocksuite/block-std": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/block-std": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/blocks": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/blocks": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/global": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/global": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/presets": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/presets": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@blocksuite/store": "npm:0.15.0-canary-202406252341-172c4b8"
|
"@blocksuite/store": "npm:0.15.0-canary-202406260417-3b9fb16"
|
||||||
"@datastructures-js/binary-search-tree": "npm:^5.3.2"
|
"@datastructures-js/binary-search-tree": "npm:^5.3.2"
|
||||||
"@testing-library/react": "npm:^16.0.0"
|
"@testing-library/react": "npm:^16.0.0"
|
||||||
async-call-rpc: "npm:^6.4.0"
|
async-call-rpc: "npm:^6.4.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user