feat(core): use new print pdf api (#7932)

This commit is contained in:
EYHN 2024-08-21 10:06:22 +00:00
parent cf086e4018
commit 3db95bafa2
No known key found for this signature in database
GPG Key ID: 46C9E26A75AB276C
17 changed files with 197 additions and 118 deletions

View File

@ -49,7 +49,7 @@
"@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-toolbar": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7", "@radix-ui/react-tooltip": "^1.0.7",
"@radix-ui/react-visually-hidden": "^1.1.0", "@radix-ui/react-visually-hidden": "^1.1.0",
"@toeverything/theme": "^1.0.5", "@toeverything/theme": "^1.0.7",
"@vanilla-extract/dynamic": "^2.1.0", "@vanilla-extract/dynamic": "^2.1.0",
"bytes": "^3.1.2", "bytes": "^3.1.2",
"check-password-strength": "^2.0.10", "check-password-strength": "^2.0.10",

View File

@ -48,7 +48,7 @@
"@sentry/integrations": "^7.109.0", "@sentry/integrations": "^7.109.0",
"@sentry/react": "^8.0.0", "@sentry/react": "^8.0.0",
"@sgtpooki/file-type": "^1.0.1", "@sgtpooki/file-type": "^1.0.1",
"@toeverything/theme": "^1.0.5", "@toeverything/theme": "^1.0.7",
"@vanilla-extract/dynamic": "^2.1.0", "@vanilla-extract/dynamic": "^2.1.0",
"animejs": "^3.2.2", "animejs": "^3.2.2",
"async-call-rpc": "^6.4.2", "async-call-rpc": "^6.4.2",

View File

@ -42,6 +42,11 @@ export const tableHeaderInfoRow = style({
fontSize: cssVar('fontSm'), fontSize: cssVar('fontSm'),
fontWeight: 500, fontWeight: 500,
minHeight: 34, minHeight: 34,
'@media': {
print: {
display: 'none',
},
},
}); });
export const tableHeaderSecondaryRow = style({ export const tableHeaderSecondaryRow = style({
@ -54,6 +59,11 @@ export const tableHeaderSecondaryRow = style({
padding: '0 6px', padding: '0 6px',
gap: '8px', gap: '8px',
height: 24, height: 24,
'@media': {
print: {
display: 'none',
},
},
}); });
export const tableHeaderCollapseButtonWrapper = style({ export const tableHeaderCollapseButtonWrapper = style({
@ -101,12 +111,26 @@ export const tableHeaderDivider = style({
borderTop: `0.5px solid ${cssVar('borderColor')}`, borderTop: `0.5px solid ${cssVar('borderColor')}`,
width: '100%', width: '100%',
margin: '8px 0', margin: '8px 0',
'@media': {
print: {
display: 'none',
},
},
}); });
export const tableBodyRoot = style({ export const tableBodyRoot = style({
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: 8, gap: 8,
'@media': {
print: {
selectors: {
'&[data-state="open"]': {
marginBottom: 32,
},
},
},
},
}); });
export const tableBodySortable = style({ export const tableBodySortable = style({
@ -124,6 +148,11 @@ export const addPropertyButton = style({
height: 36, height: 36,
fontWeight: 400, fontWeight: 400,
gap: 6, gap: 6,
'@media': {
print: {
display: 'none',
},
},
}); });
globalStyle(`${addPropertyButton} svg`, { globalStyle(`${addPropertyButton} svg`, {
fontSize: 16, fontSize: 16,

View File

@ -148,6 +148,11 @@ export const rowContainerStyle = style({
alignItems: 'center', alignItems: 'center',
padding: '4px', padding: '4px',
}); });
export const exportContainerStyle = style({
display: 'flex',
flexDirection: 'column',
gap: '8px',
});
export const labelStyle = style({ export const labelStyle = style({
fontSize: cssVar('fontSm'), fontSize: cssVar('fontSm'),
fontWeight: 500, fontWeight: 500,

View File

@ -1,20 +1,22 @@
import { ExportMenuItems } from '@affine/core/components/page-list'; import {
ExportMenuItems,
PrintMenuItems,
} from '@affine/core/components/page-list';
import { useExportPage } from '@affine/core/hooks/affine/use-export-page'; import { useExportPage } from '@affine/core/hooks/affine/use-export-page';
import { EditorService } from '@affine/core/modules/editor'; import { EditorService } from '@affine/core/modules/editor';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useService } from '@toeverything/infra';
import * as styles from './index.css'; import * as styles from './index.css';
import type { ShareMenuProps } from './share-menu';
export const ShareExport = ({ currentPage }: ShareMenuProps) => { export const ShareExport = () => {
const t = useI18n(); const t = useI18n();
const editor = useService(EditorService).editor; const editor = useService(EditorService).editor;
const exportHandler = useExportPage(currentPage); const exportHandler = useExportPage();
const currentMode = useLiveData(editor.mode$); const currentMode = useLiveData(editor.mode$);
return ( return (
<> <div className={styles.exportContainerStyle}>
<div className={styles.descriptionStyle}> <div className={styles.descriptionStyle}>
{t['com.affine.share-menu.ShareViaExportDescription']()} {t['com.affine.share-menu.ShareViaExportDescription']()}
</div> </div>
@ -25,6 +27,19 @@ export const ShareExport = ({ currentPage }: ShareMenuProps) => {
pageMode={currentMode} pageMode={currentMode}
/> />
</div> </div>
</> {currentMode === 'page' && (
<>
<div className={styles.descriptionStyle}>
{t['com.affine.share-menu.ShareViaPrintDescription']()}
</div>
<div>
<PrintMenuItems
exportHandler={exportHandler}
className={styles.exportItemStyle}
/>
</div>
</>
)}
</div>
); );
}; };

View File

@ -39,7 +39,7 @@ export const ShareMenuContent = (props: ShareMenuProps) => {
<SharePage {...props} /> <SharePage {...props} />
</Tabs.Content> </Tabs.Content>
<Tabs.Content value="export"> <Tabs.Content value="export">
<ShareExport {...props} /> <ShareExport />
</Tabs.Content> </Tabs.Content>
</Tabs.Root> </Tabs.Root>
</div> </div>

View File

@ -14,6 +14,11 @@ export const container = style({
padding: '0 24px', padding: '0 24px',
}, },
}, },
'@media': {
print: {
display: 'none',
},
},
}); });
export const dividerContainer = style({ export const dividerContainer = style({

View File

@ -168,6 +168,9 @@ export const BlocksuiteEditorContainer = forwardRef<
get mode() { get mode() {
return mode; return mode;
}, },
get origin() {
return rootRef.current;
},
}; };
const proxy = new Proxy(api, { const proxy = new Proxy(api, {

View File

@ -162,7 +162,7 @@ export const PageHeaderMenuButton = ({
} }
}, []); }, []);
const exportHandler = useExportPage(editorService.editor.doc.blockSuiteDoc); const exportHandler = useExportPage();
const handleDuplicate = useCallback(() => { const handleDuplicate = useCallback(() => {
duplicate(pageId); duplicate(pageId);

View File

@ -1,15 +1,15 @@
import { MenuItem, MenuSub } from '@affine/component'; import { MenuItem, MenuSeparator, MenuSub } from '@affine/component';
import { track } from '@affine/core/mixpanel'; import { track } from '@affine/core/mixpanel';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { import {
ExportIcon, ExportIcon,
ExportToHtmlIcon, ExportToHtmlIcon,
ExportToMarkdownIcon, ExportToMarkdownIcon,
ExportToPdfIcon,
ExportToPngIcon, ExportToPngIcon,
FileIcon,
} from '@blocksuite/icons/rc'; } from '@blocksuite/icons/rc';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useCallback, useMemo } from 'react'; import { useCallback } from 'react';
import { transitionStyle } from './index.css'; import { transitionStyle } from './index.css';
@ -22,7 +22,7 @@ interface ExportMenuItemProps<T> {
} }
interface ExportProps { interface ExportProps {
exportHandler: (type: 'pdf' | 'html' | 'png' | 'markdown') => Promise<void>; exportHandler: (type: 'pdf' | 'html' | 'png' | 'markdown') => void;
pageMode?: 'page' | 'edgeless'; pageMode?: 'page' | 'edgeless';
className?: string; className?: string;
} }
@ -47,74 +47,73 @@ export function ExportMenuItem<T>({
); );
} }
export const PrintMenuItems = ({
exportHandler,
className = transitionStyle,
}: ExportProps) => {
const t = useI18n();
return (
<ExportMenuItem
onSelect={() => exportHandler('pdf')}
className={className}
type="pdf"
icon={<FileIcon />}
label={t['com.affine.export.print']()}
/>
);
};
export const ExportMenuItems = ({ export const ExportMenuItems = ({
exportHandler, exportHandler,
className = transitionStyle, className = transitionStyle,
pageMode = 'page', pageMode = 'page',
}: ExportProps) => { }: ExportProps) => {
const t = useI18n(); const t = useI18n();
const itemMap = useMemo( return (
() => [ <>
{ <ExportMenuItem
component: ExportMenuItem, onSelect={() => exportHandler('html')}
props: { className={className}
onSelect: () => exportHandler('pdf'), type="html"
className: className, icon={<ExportToHtmlIcon />}
type: 'pdf', label={t['Export to HTML']()}
icon: <ExportToPdfIcon />, />
label: t['Export to PDF'](), {pageMode !== 'edgeless' && (
}, <ExportMenuItem
}, onSelect={() => exportHandler('png')}
{ className={className}
component: ExportMenuItem, type="png"
props: { icon={<ExportToPngIcon />}
onSelect: () => exportHandler('html'), label={t['Export to PNG']()}
className: className, />
type: 'html', )}
icon: <ExportToHtmlIcon />, <ExportMenuItem
label: t['Export to HTML'](), onSelect={() => exportHandler('markdown')}
}, className={className}
}, type="markdown"
{ icon={<ExportToMarkdownIcon />}
component: ExportMenuItem, label={t['Export to Markdown']()}
props: { />
onSelect: () => exportHandler('png'), </>
className: className,
type: 'png',
icon: <ExportToPngIcon />,
label: t['Export to PNG'](),
},
},
{
component: ExportMenuItem,
props: {
onSelect: () => exportHandler('markdown'),
className: className,
type: 'markdown',
icon: <ExportToMarkdownIcon />,
label: t['Export to Markdown'](),
},
},
],
[className, exportHandler, t]
); );
const items = itemMap.map(({ component: Component, props }) =>
pageMode === 'edgeless' &&
(props.type === 'pdf' || props.type === 'png') ? null : (
<Component key={props.label} {...props} />
)
);
return items;
}; };
export const Export = ({ exportHandler, className, pageMode }: ExportProps) => { export const Export = ({ exportHandler, className, pageMode }: ExportProps) => {
const t = useI18n(); const t = useI18n();
const items = ( const items = (
<ExportMenuItems <>
exportHandler={exportHandler} <ExportMenuItems
className={className} exportHandler={exportHandler}
pageMode={pageMode} className={className}
/> pageMode={pageMode}
/>
{pageMode !== 'edgeless' && (
<>
<MenuSeparator />
<PrintMenuItems exportHandler={exportHandler} className={className} />
</>
)}
</>
); );
const handleExportMenuOpenChange = useCallback((open: boolean) => { const handleExportMenuOpenChange = useCallback((open: boolean) => {
if (open) { if (open) {

View File

@ -4,23 +4,35 @@ import {
resolveGlobalLoadingEventAtom, resolveGlobalLoadingEventAtom,
} from '@affine/component/global-loading'; } from '@affine/component/global-loading';
import { track } from '@affine/core/mixpanel'; import { track } from '@affine/core/mixpanel';
import { apis } from '@affine/electron-api'; import { EditorService } from '@affine/core/modules/editor';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { PageRootService, RootBlockModel } from '@blocksuite/blocks'; import type { PageRootService } from '@blocksuite/blocks';
import { HtmlTransformer, MarkdownTransformer } from '@blocksuite/blocks'; import {
HtmlTransformer,
MarkdownTransformer,
printToPdf,
} from '@blocksuite/blocks';
import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store'; import type { Doc } from '@blocksuite/store';
import { useLiveData, useService } from '@toeverything/infra';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { useCallback } from 'react';
import { useAsyncCallback } from '../affine-async-hooks';
type ExportType = 'pdf' | 'html' | 'png' | 'markdown'; type ExportType = 'pdf' | 'html' | 'png' | 'markdown';
interface ExportHandlerOptions { interface ExportHandlerOptions {
page: Doc; page: Doc;
editorContainer: AffineEditorContainer;
type: ExportType; type: ExportType;
} }
async function exportHandler({ page, type }: ExportHandlerOptions) { async function exportHandler({
page,
type,
editorContainer,
}: ExportHandlerOptions) {
const editorRoot = document.querySelector('editor-host'); const editorRoot = document.querySelector('editor-host');
let pageService: PageRootService | null = null; let pageService: PageRootService | null = null;
if (editorRoot) { if (editorRoot) {
@ -37,15 +49,8 @@ async function exportHandler({ page, type }: ExportHandlerOptions) {
await MarkdownTransformer.exportDoc(page); await MarkdownTransformer.exportDoc(page);
break; break;
case 'pdf': case 'pdf':
if (environment.isDesktop && page.meta?.mode === 'page') { await printToPdf(editorContainer);
await apis?.export.savePDFFileAs( return;
(page.root as RootBlockModel).title.toString()
);
} else {
if (!pageService) return;
await pageService.exportManager.exportPdf();
}
break;
case 'png': { case 'png': {
if (!pageService) return; if (!pageService) return;
await pageService.exportManager.exportPng(); await pageService.exportManager.exportPng();
@ -54,21 +59,31 @@ async function exportHandler({ page, type }: ExportHandlerOptions) {
} }
} }
export const useExportPage = (page: Doc) => { export const useExportPage = () => {
const editor = useService(EditorService).editor;
const editorContainer = useLiveData(editor.editorContainer$);
const blocksuiteDoc = editor.doc.blockSuiteDoc;
const pushGlobalLoadingEvent = useSetAtom(pushGlobalLoadingEventAtom); const pushGlobalLoadingEvent = useSetAtom(pushGlobalLoadingEventAtom);
const resolveGlobalLoadingEvent = useSetAtom(resolveGlobalLoadingEventAtom); const resolveGlobalLoadingEvent = useSetAtom(resolveGlobalLoadingEventAtom);
const t = useI18n(); const t = useI18n();
const onClickHandler = useCallback( const onClickHandler = useAsyncCallback(
async (type: ExportType) => { async (type: ExportType) => {
if (editorContainer === null) return;
// editor container is wrapped by a proxy, we need to get the origin
const originEditorContainer = (editorContainer as any)
.origin as AffineEditorContainer;
const globalLoadingID = nanoid(); const globalLoadingID = nanoid();
pushGlobalLoadingEvent({ pushGlobalLoadingEvent({
key: globalLoadingID, key: globalLoadingID,
}); });
try { try {
await exportHandler({ await exportHandler({
page, page: blocksuiteDoc,
type, type,
editorContainer: originEditorContainer,
}); });
notify.success({ notify.success({
title: t['com.affine.export.success.title'](), title: t['com.affine.export.success.title'](),
@ -84,7 +99,13 @@ export const useExportPage = (page: Doc) => {
resolveGlobalLoadingEvent(globalLoadingID); resolveGlobalLoadingEvent(globalLoadingID);
} }
}, },
[page, pushGlobalLoadingEvent, resolveGlobalLoadingEvent, t] [
blocksuiteDoc,
editorContainer,
pushGlobalLoadingEvent,
resolveGlobalLoadingEvent,
t,
]
); );
return onClickHandler; return onClickHandler;

View File

@ -51,7 +51,7 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
}, [setInfoModalState]); }, [setInfoModalState]);
const { duplicate } = useBlockSuiteMetaHelper(docCollection); const { duplicate } = useBlockSuiteMetaHelper(docCollection);
const exportHandler = useExportPage(doc.blockSuiteDoc); const exportHandler = useExportPage();
const { setTrashModal } = useTrashModalHelper(docCollection); const { setTrashModal } = useTrashModalHelper(docCollection);
const onClickDelete = useCallback( const onClickDelete = useCallback(
(title: string) => { (title: string) => {
@ -189,7 +189,7 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
type: 'pdf', type: 'pdf',
}); });
await exportHandler('pdf'); exportHandler('pdf');
}, },
}) })
); );
@ -206,7 +206,7 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
type: 'html', type: 'html',
}); });
await exportHandler('html'); exportHandler('html');
}, },
}) })
); );
@ -223,7 +223,7 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
type: 'png', type: 'png',
}); });
await exportHandler('png'); exportHandler('png');
}, },
}) })
); );
@ -240,7 +240,7 @@ export function useRegisterBlocksuiteEditorCommands(editor: Editor) {
type: 'markdown', type: 'markdown',
}); });
await exportHandler('markdown'); exportHandler('markdown');
}, },
}) })
); );

View File

@ -1,4 +1,5 @@
import type { DocMode } from '@blocksuite/blocks'; import type { DocMode } from '@blocksuite/blocks';
import type { AffineEditorContainer } from '@blocksuite/presets';
import type { DocService, WorkspaceService } from '@toeverything/infra'; import type { DocService, WorkspaceService } from '@toeverything/infra';
import { Entity, LiveData } from '@toeverything/infra'; import { Entity, LiveData } from '@toeverything/infra';
@ -14,6 +15,8 @@ export class Editor extends Entity<{ defaultMode: DocMode }> {
readonly isSharedMode = readonly isSharedMode =
this.workspaceService.workspace.openOptions.isSharedMode; this.workspaceService.workspace.openOptions.isSharedMode;
readonly editorContainer$ = new LiveData<AffineEditorContainer | null>(null);
toggleMode() { toggleMode() {
this.mode$.next(this.mode$.value === 'edgeless' ? 'page' : 'edgeless'); this.mode$.next(this.mode$.value === 'edgeless' ? 'page' : 'edgeless');
} }
@ -22,6 +25,10 @@ export class Editor extends Entity<{ defaultMode: DocMode }> {
this.mode$.next(mode); this.mode$.next(mode);
} }
setEditorContainer(editorContainer: AffineEditorContainer | null) {
this.editorContainer$.next(editorContainer);
}
constructor( constructor(
private readonly docService: DocService, private readonly docService: DocService,
private readonly workspaceService: WorkspaceService private readonly workspaceService: WorkspaceService

View File

@ -102,8 +102,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
const isInTrash = useLiveData(doc.meta$.map(meta => meta.trash)); const isInTrash = useLiveData(doc.meta$.map(meta => meta.trash));
const { openPage, jumpToPageBlock, jumpToTag } = useNavigateHelper(); const { openPage, jumpToPageBlock, jumpToTag } = useNavigateHelper();
const [editorContainer, setEditorContainer] = const editorContainer = useLiveData(editor.editorContainer$);
useState<AffineEditorContainer | null>(null);
const isSideBarOpen = useLiveData(workbench.sidebarOpen$); const isSideBarOpen = useLiveData(workbench.sidebarOpen$);
const { appSettings } = useAppSettingHelper(); const { appSettings } = useAppSettingHelper();
@ -179,7 +178,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
usePageDocumentTitle(title); usePageDocumentTitle(title);
const onLoad = useCallback( const onLoad = useCallback(
(bsPage: BlockSuiteDoc, editor: AffineEditorContainer) => { (bsPage: BlockSuiteDoc, editorContainer: AffineEditorContainer) => {
try { try {
// todo(joooye34): improve the following migration code // todo(joooye34): improve the following migration code
const surfaceBlock = bsPage.getBlockByFlavour('affine:surface')[0]; const surfaceBlock = bsPage.getBlockByFlavour('affine:surface')[0];
@ -201,7 +200,7 @@ const DetailPageImpl = memo(function DetailPageImpl() {
} catch {} } catch {}
// blocksuite editor host // blocksuite editor host
const editorHost = editor.host; const editorHost = editorContainer.host;
// provide image proxy endpoint to blocksuite // provide image proxy endpoint to blocksuite
editorHost?.std.clipboard.use( editorHost?.std.clipboard.use(
@ -240,13 +239,20 @@ const DetailPageImpl = memo(function DetailPageImpl() {
); );
} }
setEditorContainer(editor); editor.setEditorContainer(editorContainer);
return () => { return () => {
disposable.dispose(); disposable.dispose();
}; };
}, },
[jumpToPageBlock, docCollection.id, openPage, jumpToTag, workspace.id] [
editor,
jumpToPageBlock,
docCollection.id,
openPage,
jumpToTag,
workspace.id,
]
); );
const [refCallback, hasScrollTop] = useHasScrollTop(); const [refCallback, hasScrollTop] = useHasScrollTop();

View File

@ -975,6 +975,7 @@
"com.affine.payment.billing-setting.upgrade": "Upgrade", "com.affine.payment.billing-setting.upgrade": "Upgrade",
"com.affine.payment.billing-setting.view-invoice": "View invoice", "com.affine.payment.billing-setting.view-invoice": "View invoice",
"com.affine.payment.billing-setting.year": "year", "com.affine.payment.billing-setting.year": "year",
"com.affine.export.print": "Print",
"com.affine.payment.billing-type-form.description": "Please tell us more about your use case, to make AFFiNE better.", "com.affine.payment.billing-type-form.description": "Please tell us more about your use case, to make AFFiNE better.",
"com.affine.payment.billing-type-form.go": "Go", "com.affine.payment.billing-type-form.go": "Go",
"com.affine.payment.billing-type-form.title": "Tell us your use case", "com.affine.payment.billing-type-form.title": "Tell us your use case",
@ -1276,6 +1277,7 @@
"com.affine.share-menu.SharePage": "Share doc", "com.affine.share-menu.SharePage": "Share doc",
"com.affine.share-menu.ShareViaExport": "Share via export", "com.affine.share-menu.ShareViaExport": "Share via export",
"com.affine.share-menu.ShareViaExportDescription": "Download a static copy of your doc to share with others.", "com.affine.share-menu.ShareViaExportDescription": "Download a static copy of your doc to share with others.",
"com.affine.share-menu.ShareViaPrintDescription": "Print a paper copy.",
"com.affine.share-menu.ShareWithLink": "Share with link", "com.affine.share-menu.ShareWithLink": "Share with link",
"com.affine.share-menu.ShareWithLinkDescription": "Create a link you can easily share with anyone. The visitors will open your doc in the form od a document", "com.affine.share-menu.ShareWithLinkDescription": "Create a link you can easily share with anyone. The visitors will open your doc in the form od a document",
"com.affine.share-menu.SharedPage": "Shared doc", "com.affine.share-menu.SharedPage": "Shared doc",

View File

@ -336,19 +336,6 @@ test('assert the recent browse pages are on the recent list', async ({
} }
}); });
test('can use cmdk to export pdf', async ({ page }) => {
await openHomePage(page);
await waitForEditorLoad(page);
await clickNewPageButton(page);
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill('this is a new page to export');
await openQuickSearchByShortcut(page);
const [download] = await Promise.all([
page.waitForEvent('download'),
keyboardDownAndSelect(page, 'Export to PDF'),
]);
expect(download.suggestedFilename()).toBe('this is a new page to export.pdf');
});
test('can use cmdk to export png', async ({ page }) => { test('can use cmdk to export png', async ({ page }) => {
await openHomePage(page); await openHomePage(page);
await waitForEditorLoad(page); await waitForEditorLoad(page);

View File

@ -326,7 +326,7 @@ __metadata:
"@storybook/react": "npm:^8.2.9" "@storybook/react": "npm:^8.2.9"
"@storybook/react-vite": "npm:^8.2.9" "@storybook/react-vite": "npm:^8.2.9"
"@testing-library/react": "npm:^16.0.0" "@testing-library/react": "npm:^16.0.0"
"@toeverything/theme": "npm:^1.0.5" "@toeverything/theme": "npm:^1.0.7"
"@types/bytes": "npm:^3.1.4" "@types/bytes": "npm:^3.1.4"
"@types/react": "npm:^18.2.75" "@types/react": "npm:^18.2.75"
"@types/react-dnd": "npm:^3.0.2" "@types/react-dnd": "npm:^3.0.2"
@ -422,7 +422,7 @@ __metadata:
"@sgtpooki/file-type": "npm:^1.0.1" "@sgtpooki/file-type": "npm:^1.0.1"
"@swc/core": "npm:^1.4.13" "@swc/core": "npm:^1.4.13"
"@testing-library/react": "npm:^16.0.0" "@testing-library/react": "npm:^16.0.0"
"@toeverything/theme": "npm:^1.0.5" "@toeverything/theme": "npm:^1.0.7"
"@types/animejs": "npm:^3.1.12" "@types/animejs": "npm:^3.1.12"
"@types/bytes": "npm:^3.1.4" "@types/bytes": "npm:^3.1.4"
"@types/image-blob-reduce": "npm:^4.1.4" "@types/image-blob-reduce": "npm:^4.1.4"
@ -13858,10 +13858,10 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@toeverything/theme@npm:^1.0.2, @toeverything/theme@npm:^1.0.5": "@toeverything/theme@npm:^1.0.2, @toeverything/theme@npm:^1.0.7":
version: 1.0.5 version: 1.0.7
resolution: "@toeverything/theme@npm:1.0.5" resolution: "@toeverything/theme@npm:1.0.7"
checksum: 10/26f177192c546b8b6c953a4d75da5520486fa92c872b889052861cd121ef9840b5006e2f1513988117290066812e08015aa99b025d13c01ca50563a9ba26a732 checksum: 10/86b46af255450ab7ea0a20faf41c27793129852759d23736e914876a696c40e6daa15b25cde7353cd56c673c6191d04cabe6b77f6131ba0b0862bb8d482d7a01
languageName: node languageName: node
linkType: hard linkType: hard