Important
Retired on 2026-10-21. Catalog data is now edited in one place, the NextMoe editor at editor.nextmoe.com. The forum, moyu and LetMoe link straight to it, so these packages have no consumers left: they are deprecated on npm, this repository is archived, and the edit-ui.nextmoe.dev demo is offline. To send users to the editor from your own site, see the editor integration guide.
The schema-driven edit component family of the NextMoe ecosystem — the form that renders an entity's editable fields from a server-sent schema, the per-field controls, and the diff / proposal / revision views that go with them.
Third family alongside KunUI (@kungal/ui-*)
and KunEditor (@kungal/editor-*). It
composes KunUI — it does not fork, wrap or re-style it.
| Package | What it is |
|---|---|
@nextmoe/edit-ui-core |
Framework-free TypeScript: the wire/schema types + the pure diff, formatting and badge helpers. No Vue anywhere in its dependency closure. |
@nextmoe/edit-ui-vue |
The Vue 3 components. Peer deps: vue ^3.5, @kungal/ui-vue ^2.26.2. |
@nextmoe/edit-ui-nuxt |
A Nuxt module that auto-imports the components under a configurable prefix (default Edit). |
apps/playground is that site: a private Nuxt app — a landing page plus a
zh-CN docs section — that renders every control and view off a fixture schema.
The visual check while developing, and the public demo once deployed.
pnpm add @nextmoe/edit-ui-nuxt @nextmoe/edit-ui-vue @nextmoe/edit-ui-core// nuxt.config.ts
export default defineNuxtConfig({
extends: ['@kungal/ui-nuxt'],
modules: ['@nextmoe/edit-ui-nuxt'],
editUi: { prefix: 'Edit' } // default; `global: true` also available
})<EditSchemaForm :fields="fields" :values="values" :config="config" />The prefix is why the module exists: a site migrating off a local copy of these
components can keep its own tag names (prefix: 'Editkit' → <EditkitSchemaForm>)
and change zero templates.
import { SchemaForm, FieldDiff } from '@nextmoe/edit-ui-vue'
import type { EditFieldConfigMap } from '@nextmoe/edit-ui-vue'Components are exported under their bare names; the prefix is applied only by the Nuxt module.
The packages ship no CSS. Every class is a KunUI semantic token
(text-default-500, bg-content1, border-default-200, text-danger-600 …), so
the host app needs KunUI's Tailwind entry and must include this package in its
Tailwind @source scan:
@import 'tailwindcss';
@import '@kungal/ui-tokens';
@import '@kungal/ui-vue/style.css';
@source '../../node_modules/@kungal/ui-vue';
@source '../../node_modules/@nextmoe/edit-ui-vue/dist';Paths are relative to the CSS file, and dist is the only directory the package
publishes. Miss the line and the components render with no error and no styling —
the guide says more.
No gradient backgrounds are used anywhere, and none may be added.
These components know how to render an edit surface. They know nothing about
your API, your image host, or your entity catalogue. Everything that touches a
backend is a function the site provides through EditFieldConfig:
| Field config key | Signature | The site's job |
|---|---|---|
uploadImage |
(file, currentItems) => Promise<item | null> |
Upload a picture, return the item to store. Absent ⇒ the image field renders read-only. |
resolveImage |
(value) => string |
Turn a stored image value into a displayable URL. |
searchEntities |
(keyword) => Promise<EditSelectOption[]> |
Search the entity catalogue for the pickers. |
resolveEntities |
(ids) => EditSelectOption[] | Promise<...> |
Turn already-stored ids back into labels. |
There is no default, no fallback fetch and no built-in endpoint. A picker with no
searchEntities simply does not render as a picker.
The edit engine may start sending a control (or a schema kind) that an
installed package predates. SchemaField renders such a field as a read-only
text / JSON display instead of throwing or falling through to a text input that
would invite an unsaveable edit. isEditControl() from the core package is the
check; EDIT_CONTROLS is the list it is derived from.
This is a contract, pinned by packages/vue/src/SchemaField.spec.ts: an old
package in production must not break when the engine ships a new render hint.
pnpm install
pnpm build # core (tsup) → vue (vite + vue-tsc d.ts) → nuxt → playground
pnpm typecheck
pnpm test
pnpm --filter @nextmoe/edit-ui-playground dev # http://localhost:6898Releases go through changesets:
pnpm changeset, then pnpm ci:version / pnpm ci:publish. The three published
packages are versioned in lockstep.
apps/playground is also the public site. .github/workflows/docs-image.yml
builds docker/docs.Dockerfile on every push to main that touches the app or
the packages and pushes ghcr.io/next-moe/nextmoe-edit-ui-docs:latest;
docker-compose.prod.yml is what Dokploy runs (internal port 6760, routed to
edit-ui.nextmoe.dev by its Traefik). Production never builds.
Extracted from the editkit component family of
kun-galgame-forum
(apps/web/app/components/editkit/) at commit
f099ad0b5dfb20c71716332b6c3e4c459d59e41e, behaviour-preserving.
AGPL-3.0-only. See LICENSE.