feat(creator-studio): icon toolbar with block tools, drop author strip

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-06 22:30:08 +08:00
1 parent 7bdf7cf018
commit 7c33482be7
19 files changed
+600 -241

No files matched your search

+34 -14
View File
@@ -7,18 +7,18 @@
* @package Jio
*/
import { createRoot, useCallback, useEffect, useMemo, useRef, useState } from '@wordpress/element';
import { createRoot, useCallback, useEffect, useRef, useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import { apiPost } from './services/api';
import { PublishDrawer } from './panels/publish-drawer';
import { EditorToolbar } from './components/editor-toolbar';
import { PublishSettings } from './components/publish-settings';
import { AuthorRow } from './components/author-row';
import { SaveState, type SaveStateValue } from './components/save-state';
import { useAutosave } from './hooks/use-autosave';
import { useLocalRecovery } from './hooks/use-local-recovery';
import { normalizePayForRequest } from './utils/pay';
import { codeBlockMarkup, dividerMarkup, footnoteMarkup, listMarkup, mathMarkup, tableMarkup, tocMarkup } from './utils/block-markup';
import './styles/studio.scss';
const bootstrap: Record<string, any> = window['jioCreatorStudio'] || {};
@@ -184,8 +184,6 @@ function Studio(): JSX.Element {
setFormatValue(['h1', 'h2', 'h3', 'blockquote'].includes(name) ? name : 'p');
}, []);
const charCount = useMemo(() => Array.from(plainText(draft.content)).length, [draft.content]);
const buildPayload = useCallback((extra: Record<string, any> = {}) => {
const current = draftRef.current;
return {
@@ -510,7 +508,31 @@ function Studio(): JSX.Element {
}
}, [focusEditor]);
const openMedia = useCallback((type: 'image' | 'video') => {
const insertBlock = useCallback((kind: string) => {
const editor = focusEditor();
if (!editor) {
return;
}
const markup: Record<string, string> = {
list: listMarkup(false),
toc: tocMarkup(),
divider: dividerMarkup(),
code: codeBlockMarkup(),
footnote: footnoteMarkup(),
math: mathMarkup(),
table: tableMarkup(),
};
const html = markup[kind];
if (!html) {
return;
}
editor.insertContent(html);
editor.nodeChanged();
updateContent(editor.getContent());
updateHistoryAvailability(editor);
}, [focusEditor]);
const openMedia = useCallback((type: 'image' | 'video' | 'file') => {
const editor = editorRef.current;
const media = (window as any).JioSubmitMedia;
if (!editor || !media || typeof media.open !== 'function') {
@@ -535,6 +557,10 @@ function Studio(): JSX.Element {
const fullAttribute = fullUrl ? ` data-full-url="${escapeAttribute(fullUrl)}"` : '';
return `<p><img src="${escapeAttribute(url)}"${idAttribute} alt="${escapeAttribute(String(item.name || item.title || ''))}"${fullAttribute}></p>`;
}
if (type === 'file') {
const name = String(item.filename || item.name || url.split('/').pop() || '');
return `<p><a class="jio-file-link" href="${escapeAttribute(url)}"${idAttribute}><i class="fa fas fa-paperclip" aria-hidden="true"></i> ${escapeAttribute(name)}</a></p>`;
}
return `<div contenteditable="false" data-video-url="${escapeAttribute(url)}" data-video-name="${escapeAttribute(String(item.filename || item.name || url))}"${idAttribute} class="new-dplayer post-dplayer dplayer"></div><p></p>`;
}).join('');
if (markup) {
@@ -572,8 +598,8 @@ function Studio(): JSX.Element {
<EditorToolbar
ready={editorReady}
formatValue={formatValue}
onFormatChange={setFormatValue}
formatValue={formatValue}
onFormatChange={setFormatValue}
canUndo={historyAvailability.canUndo}
canRedo={historyAvailability.canRedo}
capabilities={capabilities}
@@ -581,6 +607,7 @@ function Studio(): JSX.Element {
onRememberSelection={rememberSelection}
onOpenLink={openLink}
onOpenMedia={openMedia}
onInsertBlock={insertBlock}
/>
<div className="jio-creator__bar-actions jio-creator__toolbar-extension" data-toolbar-extension aria-label={__('工具扩展区', 'jio')}>
<SaveState value={saveState} />
@@ -618,8 +645,6 @@ function Studio(): JSX.Element {
)}
<main className="jio-creator__canvas">
<AuthorRow author={bootstrap.author || {}} />
<label className="jio-creator__title">
<span className="screen-reader-text">{__('文章标题', 'jio')}</span>
<textarea
@@ -651,11 +676,6 @@ function Studio(): JSX.Element {
onScheduleChange={(enabled, at) => patchDraft({ schedule: { enabled, at } })}
/>
<footer className="jio-creator__footer">
<span>{__('字数', 'jio')}:{charCount}</span>
<span>{__('约', 'jio')} {Math.max(1, Math.round(charCount / 400))} {__('分钟阅读', 'jio')}</span>
</footer>
{drawerOpen && (
<PublishDrawer
draft={draft}