@basenative /建设者
BaseNative的基于信号的拖放组件构建器。可视化地组合布局,通过响应式检查器编辑道具,并生成干净的BaseNative模板代码作为输出。
- 零依赖关系 除了
@basenative/runtime. - 狗粮:消极的信号 -每个建设者状态都是一个
signal(). - 原生HTML5拖放 -没有阴影DOM,没有自定义DnD层。
- 语义HTML 完整的ARIA角色(
role="tree",role="application",role="toolbar")。 display: contents在每个主元素上 -包装不影响布局。- csp安全代码生成 -输出是纯HTML/模板;否
eval.
安装
pnpm add @basenative/builder
快速启动(程序化)
import { createBuilderState, defaultPalette, generateBaseNative } from '@basenative/builder';
const palette = defaultPalette();
const state = createBuilderState();
const hero = state.addNode(null, { type: 'section', props: { class: 'hero' } });
state.addNode(hero.id, { type: 'heading', props: { level: 'h1', text: 'Welcome' } });
state.addNode(hero.id, { type: 'text', props: { text: 'A quiet runtime.' } });
console.log(generateBaseNative(state, { palette }));
输出:
<section class="hero" role="region">
<h1>Welcome</h1>
<p>A quiet runtime.</p>
</section>
快速启动(在浏览器中)
<bn-builder></bn-builder>
<script type="module">
import '@basenative/builder';
const builder = document.querySelector('bn-builder');
builder.addEventListener('bn-builder-export', (e) => {
console.log(e.detail.code);
});
</script>
这个 <bn-builder> 元素安装四个窗格:
| 元素 | 角色 |
|---|---|
<bn-builder-palette> | 组件的拖动源 |
<bn-builder-canvas> | 掉落目标-树的实时预览 |
<bn-builder-tree> | 节点的层次轮廓 |
<bn-builder-inspector> | 用于编辑道具和信号绑定的响应式表单 |
信号绑定
每个节点都有一个 bindings 将道具名称连接到用户作用域中的信号的映射。代码将其作为BaseNative指令发出:
const node = state.addNode(null, { type: 'input' });
state.setBinding(node.id, 'value', { ref: 'username' });
generateBaseNative(state, { palette, signals: { username: '' } });
输出:
<script type="module">
import { signal } from '@basenative/runtime';
const username = signal("");
</script>
<input type="text" @bind="username" />
对于文本内容:
state.setBinding(id, 'text', { ref: 'count' });
// → <span>{{ count() }}</span>
公共API
createBuilderState(options?): BuilderState
createPalette(): ComponentPalette
defaultPalette(): ComponentPalette
generateBaseNative(state, options?): string
renderTreeView(state): string
renderInspector(state, palette): string
BuilderState 暴露信号(tree, selection, hover, canUndo, canRedo)和行动(addNode, removeNode, updateProps, setBinding, moveNode, duplicateNode, select, undo, redo, clear, toJSON, fromJSON, subscribe)。
信号是一流的——把它们连接到你自己的 effect() 对用户编辑作出反应:
import { effect } from '@basenative/runtime';
effect(() => console.log('Tree size:', state.tree().length));
默认的面板
| 类型 | 标签 | 容器 | 类别 |
|---|---|---|---|
section | <section role="region"> | 是 | 布局 |
stack | <div> | 是 | 布局 |
grid | <div> | 是 | 布局 |
heading | <h1>–<h6> | 否 | 文本 |
text | <p> | 否 | 文本 |
button | <button> | 否 | 输入 |
input | <input> | 否 | 输入 |
textarea | <textarea> | 否 | 输入 |
checkbox | <input type="checkbox"> | 否 | 输入 |
label | <label> | 是 | 输入 |
form | <form> | 是 | 输入 |
link | <a> | 否 | 导航 |
image | <img> | 否 | 媒体 |
signal-text | <span>{{ … }}</span> | 否 | 无功 |
注册你自己的:
palette.register({
type: 'kbd',
tag: 'kbd',
category: 'text',
props: [{ name: 'text', kind: 'string', label: 'Key' }],
defaults: { text: '⌘K' },
});
持久性
const json = state.toJSON();
// store somewhere
state.fromJSON(json); // wipes history, hydrates tree
键盘快捷键(画布)
| 键 | 行动 |
|---|---|
Delete / Backspace | 移除所选节点 |
Cmd/Ctrl + Z | 撤销 |
Cmd/Ctrl + Shift + Z / Cmd/Ctrl + Y | 重做 |
测试
cd packages/builder && node --test
编写测试时使用 node:test -不需要Jest,不需要Vitest,不需要纯逻辑的浏览器控制。Web组件测试需要一个DOM,并在下游应用程序中进行。
许可证
apache - 2.0