@axhub/commentary-react
v1.0.0
Published
`@axhub/commentary-react` 是给 React 宿主用的一层轻量客户端辅助。
Readme
@axhub/commentary-react
@axhub/commentary-react 是给 React 宿主用的一层轻量客户端辅助。
它不定义业务字段,也不替宿主决定哪些属性可编辑,只做三件事:
- 提供一个
useSyncExternalStore风格的 tweak store - 把 React 侧状态包装成 Commentary 可识别的 tweak adapter
- 帮宿主把元素级 tweak 能力注册到全局协议中
协议本身仍然是框架无关的,未来 Vue / jQuery / 原生 DOM 宿主也可以直接实现同一套协议。
安装
import {
createCommentaryReactTweakStore,
createCommentaryReactTweakAdapter,
useCommentaryReactTweakStore,
useRegisterCommentaryTweak,
} from '@axhub/commentary-react';何时使用
适合以下场景:
- 宿主本身是 React 页面
- 元素的 tweak 值已经存在于 React state / props / store 中
- 希望让 Commentary 的
"调整"tab 直接消费这些值
不适合以下场景:
- 想把页面级全局配置直接映射为 tweak
- 想让 editor 内置一套固定可编辑字段
- 想把 tweak 设计成只读静态 schema 且没有 element 绑定关系
核心概念
1. store
createCommentaryReactTweakStore(initialValues) 创建一个最小外部 store:
const tweakStore = createCommentaryReactTweakStore({
title: '旧标题',
visible: true,
});它提供:
getSnapshot()subscribe(listener)set(nextValues)update(patch)
如果组件里想直接消费这个 store,可以用:
const values = useCommentaryReactTweakStore(tweakStore);2. schema
schema 完全由宿主决定。编辑器只识别通用字段描述,不提供业务字段白名单。
const tweakSchema = {
title: '卡片配置',
description: '这些配置绑定到当前卡片实例。',
fields: [
{
key: 'title',
label: '标题',
type: 'text',
},
{
key: 'visible',
label: '显示',
type: 'switch',
},
],
};当前支持的 type:
texttextareanumberselectswitchcolor
3. 注册到全局 tweak protocol
最简单的 React 用法是直接使用 useRegisterCommentaryTweak(...):
import React from 'react';
import {
createCommentaryReactTweakStore,
useRegisterCommentaryTweak,
} from '@axhub/commentary-react';
const tweakSchema = {
title: '卡片配置',
fields: [
{ key: 'title', label: '标题', type: 'text' },
{ key: 'visible', label: '显示', type: 'switch' },
],
};
export function SalesCard() {
const rootRef = React.useRef<HTMLDivElement | null>(null);
const tweakStore = React.useMemo(
() =>
createCommentaryReactTweakStore({
title: '本周销售额',
visible: true,
}),
[],
);
useRegisterCommentaryTweak({
elementRef: rootRef,
schema: tweakSchema,
store: tweakStore,
onUpdate: async (patch) => {
tweakStore.update(patch);
},
});
return <div ref={rootRef}>...</div>;
}行为说明:
- 只要
elementRef.current和schema都可用,hook 就会注册 adapter - 组件卸载时会自动注销
- editor 选中该元素后,如果
schema.fields.length > 0,会显示"调整"tab "调整"tab 会排在"样式"前面
手动创建 adapter
如果你不想用 hook,也可以手动创建 adapter:
import {
ensureGlobalCommentaryTweakProtocol,
} from '@axhub/commentary-react';
import {
createCommentaryReactTweakAdapter,
createCommentaryReactTweakStore,
} from '@axhub/commentary-react';
const element = document.querySelector('#sales-card') as Element;
const store = createCommentaryReactTweakStore({ title: '销售额' });
const unregister = ensureGlobalCommentaryTweakProtocol().register(
createCommentaryReactTweakAdapter({
element,
schema: {
fields: [{ key: 'title', label: '标题', type: 'text' }],
},
store,
onUpdate: async (patch) => {
store.update(patch);
},
}),
);与 editor 的关系
React 包只负责注册,真正的消费方仍然是 tweak protocol:
- editor 通过
window.__AXHUB_COMMENTARY_TWEAK_PROTOCOL__读取 adapter - editor 在 property panel 中读取
getSchema(element)/getValues(element) - editor 在用户修改时调用
update(element, patch) - editor 会把 tweak 改动写入变更摘要,并在 prompt 中排到样式前面
约束
- tweak 是元素级绑定,不是页面级全局配置
- schema / values / update 必须由宿主控制
- editor 不保证通用“恢复默认值”语义,当前回退仍然依赖宿主 adapter 接受回写 patch
- React 包只是便捷层,不会改变底层协议
