@joai / sdk
React入口点包含可重用的构建块,用于在客户端网站上编辑内容。组件保持域中立:站点提供标识符、复制、样式挂钩和呈现字段;SDK拥有会话切换和编辑生命周期。
托管内容编辑器
import { ManagedContentEditor } from '@joai/react'
<ManagedContentEditor
config={{
contentId: 'content-id',
publicSlug: 'website-content',
sessionStorageKey: 'website-content-session',
team: 'team-slug',
}}
initialContent={content}
title="Inhalte bearbeiten"
labels={{
edit: 'Bearbeiten',
save: 'Entwurf speichern',
saving: 'Wird gespeichert …',
publish: 'Veröffentlichen',
publishing: 'Wird veröffentlicht …',
cancel: 'Abbrechen',
toolbar: 'Inhaltseditor',
unsaved: 'Nicht gespeicherte Änderungen',
}}
messages={{
conflict: 'Der Inhalt wurde zwischenzeitlich geändert. Deine Eingaben bleiben erhalten. Bitte prüfe sie und versuche es erneut.',
loadError: 'Der Inhalt konnte nicht geladen werden.',
publishError: 'Die Änderungen konnten nicht veröffentlicht werden.',
published: 'Die Änderungen wurden veröffentlicht.',
saveError: 'Der Entwurf konnte nicht gespeichert werden.',
saved: 'Der Entwurf wurde gespeichert.',
sessionExpired: 'Deine Sitzung ist abgelaufen.',
unsavedNavigation: 'Du hast nicht gespeicherte Änderungen. Seite wirklich verlassen?',
}}
imagePickerLabels={{
applyCrop: 'Zuschnitt übernehmen',
back: 'Zurück',
choose: 'Bild auswählen',
close: 'Schließen',
cropDescription: 'Passe Bildausschnitt und Zoom vor dem Hochladen an.',
cropTitle: 'Bild zuschneiden',
dimensionsTooLarge: 'Die Bildabmessungen sind zu groß.',
dimensionsTooSmall: 'Die Bildabmessungen sind zu klein.',
drop: 'Bild hier ablegen',
empty: 'Noch keine Bilder vorhanden.',
field: 'Bearbeitbares Bild',
invalidType: 'Bitte wähle eine Bilddatei.',
libraryDescription: 'Wähle ein vorhandenes Bild oder lade ein neues hoch.',
libraryTitle: 'Bildmediathek',
loadError: 'Bilder konnten nicht geladen werden.',
loading: 'Bilder werden geladen …',
positionHorizontal: 'Horizontale Position',
positionVertical: 'Vertikale Position',
processing: 'Bild wird vorbereitet …',
retry: 'Erneut versuchen',
tooLarge: 'Das Bild ist zu groß.',
upload: 'Bild hochladen',
uploadError: 'Das Bild konnte nicht hochgeladen werden.',
uploading: 'Wird hochgeladen …',
zoom: 'Zoom',
}}
reauthenticateLabel="Anmeldung erneuern"
sessionExpiredMessage="Deine Sitzung ist abgelaufen. Deine lokalen Änderungen bleiben erhalten."
confirmCancel={() => window.confirm('Nicht gespeicherte Änderungen verwerfen?')}
confirmLeave={() => window.confirm('Du hast nicht gespeicherte Änderungen. Seite wirklich verlassen?')}
confirmPublish={() => window.confirm('Änderungen jetzt veröffentlichen?')}
>
{children}
</ManagedContentEditor>
使用 EditableContent, EditableImage, useContentValue 从 @joai/react 编辑器内部。将服务器获取的公共内容传递为 initialContent 以避免访问者的客户端加载状态。
将每个图像字段配置为可重用的、与领域无关的构建块。默认情况下,图像被压缩为WebP,最高可达2560 × 2560像素,而动画GIF和SVG文件保留其原始格式。每个领域的种植是可选择的:
<EditableImage
field="heroImage"
label="Titelbild"
maxSourceBytes={40 * 1024 * 1024}
maxUploadBytes={5 * 1024 * 1024}
processing={{
crop: { aspectRatio: 16 / 9, outputWidth: 1920 },
compression: { maxWidth: 1920, maxHeight: 1080, mimeType: 'image/webp', quality: 0.84 },
dimensions: { minWidth: 1280, minHeight: 720, maxPixels: 50_000_000 },
}}
/>
集 compression: false 或者 dimensions: false 仅禁用该阶段,或者 processing={false} 上传原始图像,无需客户端解码、验证、裁剪或压缩。
会话存储
useContentSession 和 createSessionTokenStore 为自定义shell导出。一个自定义 SessionTokenStore 可以在主机需要不同的持久性机制时注入。包含一次性移交令牌的URL片段在交换和持久化之前被删除。
托管编辑器会自动添加 platform=app 到它的重新身份验证返回URL,这样JoAi返回一个一次性的移交令牌。覆盖 reauthenticateUrl 只有当主机有专用的登录回调时。
createContentDraftStore 使用 sessionStorage 默认情况下。 ManagedContentEditor 自动连接,使未保存的值在刷新和过期会话重新身份验证中存活下来,而不会跨浏览器会话共享。
编辑行为
- 取消将恢复当前加载的版本。
- 当没有本地更改时,将禁用Save。
- 脏发布使用一个请求保存和发布。
- 网络故障使本地编辑可用于重试。
- 未保存编辑时,刷新、关闭和链接/导航尝试会发出警告。
- 可编辑的文本和图像字段在编辑模式下可见地标记。
- 图像库支持加载、空、错误、字节/尺寸验证、裁剪、压缩、键盘、焦点和拖放状态。
- 过期的授权提供登录操作,并在之后恢复本地持久编辑。
- 版本冲突将加载最新版本,同时保留本地编辑。
- 公共内容缓存项在经过身份验证的更改之后无效。