npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@axhub/genie-editor-client

v0.0.1

Published

`@axhub/genie-editor-client` 是给 Genie Editor 宿主侧使用的一层轻量客户端集成工具包。

Downloads

140

Readme

@axhub/genie-editor-client

@axhub/genie-editor-client 是给 Genie Editor 宿主侧使用的一层轻量客户端集成工具包。

当前首批能力聚焦在 React tweak helper,但它的定位不是只服务 React hook,而是承接页面宿主与 axhub-genie-editor 对接时需要的客户端侧工具。

对外使用口径

如果你是这个 npm 包的使用方,对外只需要关注:

  • 安装 @axhub/genie-editor-client
  • 所有 import 都从 @axhub/genie-editor-client 读取
  • 把 schema / values / adapter 注册到全局 tweak protocol

axhub-genie-editor 是当前仓库里的 editor 运行时消费方,用来读取你注册到页面全局的 tweak protocol。它不是这个 README 面向的安装入口,也不是你在宿主项目里需要直接依赖的包。

它不定义业务字段,也不替宿主决定哪些属性可编辑,只做三件事:

  • 提供一个 useSyncExternalStore 风格的 tweak store
  • 把 React 侧状态包装成 Genie Editor 可识别的 tweak adapter
  • 帮宿主把元素级 tweak 能力注册到全局协议中

协议本身仍然是框架无关的,未来 Vue / jQuery / 原生 DOM 宿主也可以直接实现同一套协议。

安装

import {
  createGenieEditorReactTweakStore,
  createGenieEditorReactTweakAdapter,
  useGenieEditorReactTweakStore,
  useRegisterGenieEditorTweak,
} from '@axhub/genie-editor-client';

如果你的宿主需要直接访问协议类型,也可以直接从同一个包导入:

import type {
  GenieEditorTweakSchema,
  GenieEditorTweakValues,
} from '@axhub/genie-editor-client';

如果你的宿主需要在“字段结构变了但没有重建 adapter”时手动刷新 editor,也可以导入:

import { notifyGlobalGenieEditorTweakProtocol } from '@axhub/genie-editor-client';

何时使用

适合以下场景:

  • 宿主本身是 React 页面
  • 元素的 tweak 值已经存在于 React state / props / store 中
  • 希望让 Genie Editor 的 "调整" tab 直接消费这些值

不适合以下场景:

  • 想把页面级全局配置直接映射为 tweak
  • 想让 editor 内置一套固定可编辑字段
  • 想把 tweak 设计成只读静态 schema 且没有 element 绑定关系

核心概念

1. store

createGenieEditorReactTweakStore(initialValues) 创建一个最小外部 store:

const tweakStore = createGenieEditorReactTweakStore({
  title: '旧标题',
  visible: true,
});

它提供:

  • getSnapshot()
  • subscribe(listener)
  • set(nextValues)
  • update(patch)

如果组件里想直接消费这个 store,可以用:

const values = useGenieEditorReactTweakStore(tweakStore);

2. schema

schema 完全由宿主决定。编辑器只识别通用字段描述,不提供业务字段白名单。

const tweakSchema = {
  title: '卡片配置',
  description: '这些配置绑定到当前卡片实例。',
  fields: [
    {
      key: 'title',
      label: '标题',
      type: 'text',
    },
    {
      key: 'visible',
      label: '显示',
      type: 'switch',
    },
  ],
} satisfies GenieEditorTweakSchema;

当前支持的 type

  • text
  • number
  • slider
  • select
  • card
  • checkbox
  • switch
  • color

其中 card 适合表达纵向单选卡片。每个选项使用:

  • label 作为卡片标题
  • description 作为卡片描述
  • value 作为实际回写值

3. 注册到全局 tweak protocol

最简单的 React 用法是直接使用 useRegisterGenieEditorTweak(...)

import React from 'react';
import {
  createGenieEditorReactTweakStore,
  useRegisterGenieEditorTweak,
} from '@axhub/genie-editor-client';
import type { GenieEditorTweakSchema } from '@axhub/genie-editor-client';

const tweakSchema: GenieEditorTweakSchema = {
  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(
    () =>
      createGenieEditorReactTweakStore({
        title: '本周销售额',
        visible: true,
      }),
    [],
  );

  useRegisterGenieEditorTweak({
    elementRef: rootRef,
    schema: tweakSchema,
    store: tweakStore,
    onUpdate: async (patch) => {
      tweakStore.update(patch);
    },
  });

  return <div ref={rootRef}>...</div>;
}

行为说明:

  • 只要 elementRef.currentschema 都可用,hook 就会注册 adapter
  • 组件卸载时会自动注销
  • 注册和注销都会自动通知 Genie Editor 刷新全局 tweak 列表
  • store 通过 subscribe 推送值变化时,Genie Editor 会自动回读最新 values
  • editor 选中该元素后,如果 schema.fields.length > 0,会显示 "调整" tab
  • "调整" tab 会排在 "样式" 前面

这意味着大多数 React 场景不需要你手动调用刷新函数:

  • 组件挂载 / 卸载
  • HMR 导致 hook 重新注册
  • store.set(...) / store.update(...)

这些都会自动反映到 Genie Editor。

手动创建 adapter

如果你不想用 hook,也可以手动创建 adapter:

import { ensureGlobalGenieEditorTweakProtocol } from '@axhub/genie-editor-client';
import {
  createGenieEditorReactTweakAdapter,
  createGenieEditorReactTweakStore,
} from '@axhub/genie-editor-client';

const element = document.querySelector('#sales-card') as Element;
const store = createGenieEditorReactTweakStore({ title: '销售额' });

const unregister = ensureGlobalGenieEditorTweakProtocol().register(
  createGenieEditorReactTweakAdapter({
    element,
    schema: {
      fields: [{ key: 'title', label: '标题', type: 'text' }],
    },
    store,
    onUpdate: async (patch) => {
      store.update(patch);
    },
  }),
);

什么时候需要显式刷新

如果你是“原地修改” schema,而不是让 hook / adapter 重新注册,Genie Editor 不一定知道字段结构已经变了。这类场景可以显式通知一次:

import { notifyGlobalGenieEditorTweakProtocol } from '@axhub/genie-editor-client';

mutableSchema.fields = [
  { key: 'title', label: '标题', type: 'text' },
  { key: 'theme', label: '主题色', type: 'color' },
];

notifyGlobalGenieEditorTweakProtocol();

更适合显式刷新的场景:

  • 你在原对象上 push / splice schema.fields
  • 你改变了 adapter 的匹配逻辑,但没有重新注册
  • 你把多个外部数据源合并成一个 schema,变化发生在 React 之外

如果你已经让 useRegisterGenieEditorTweak(...) 因为依赖变化而重新注册 adapter,通常就不需要再手动刷新。

与 editor 的关系

客户端包只负责注册和协议桥接。对外使用时,你只需要依赖 @axhub/genie-editor-client;如果页面里存在 Genie Editor 运行时,它会去消费这些全局注册的数据。

当前仓库里的 editor 消费方式是:

  • editor 通过 window.__AXHUB_GENIE_EDITOR_TWEAK_PROTOCOL__ 读取 adapter
  • editor 在 property panel 中读取 getSchema(element) / getValues(element)
  • editor 在用户修改时调用 update(element, patch)
  • editor 在 adapter 注册、注销、订阅更新、显式 notify() 后刷新 tweak 视图
  • editor 会把 tweak 改动写入变更摘要,并在 prompt 中排到样式前面

约束

  • tweak 是元素级绑定,不是页面级全局配置
  • schema / values / update 必须由宿主控制
  • editor 不保证通用“恢复默认值”语义,当前回退仍然依赖宿主 adapter 接受回写 patch
  • 客户端包里的 React helper 只是便捷层,不会改变底层协议