No description
Addresses four user-reported gaps in the visual mode authoring surface:
1. × button and expand chevron triggered a drag instead of their own
action. dnd-kit listeners were spread on the outer SortableBlockItem
wrapper, so any pointerdown on a descendant started a sort. Fixed by
routing only `listeners` to a new dedicated grip-handle icon on the
card header; the rest of the card (× / expand / inspector / body)
no longer competes with drag. `attributes` still go on the wrapper
so keyboard drag + screen-reader announcements keep working.
2. No way to add primitives INSIDE a trigger — palette clicks always
appended at the top level. Fixed by computing an addTargetInfo when
the selected block is a container (has childPrimitives + a params
.primitives array): the palette now shows an "Adding inside: {label}"
banner with an "Add at top level instead" escape button, and
handleAddPrimitive routes the new node into the parent params. The
parent auto-expands and selection stays on the parent so repeated
palette clicks stack children under it.
3. Inspector was read-only — ParamField.onChange was a documented
no-op. Fixed by adding onParamsChange through the wire
(VisualBuilderPane.handleParamsChange → BlockList.onParamsChange
→ SortableBlockItem.onParamsChange → BlockCard.onParamsChange →
ParamField.onChange). Editing a number/string/enum field now
immediately updates descriptor.primitives[index].params.
4. Nested children could not be removed — nested BlockList was given
onRemove={() => {}}. Fixed by adding onNestedRemove to BlockListProps;
VisualBuilderPane supplies handleNestedRemove which filters the
matching parent params.primitives[] without mutating siblings.
Additional polish:
- Inspector now opens when a block is selected (previously needed
selected AND expanded), so children and docs show up on first click.
- Child block list renders whenever the parent is expanded OR selected
for the same first-click visibility.
- Expand button gains aria-label="Expand|Collapse" so accessibility
tooling (and Playwright getByRole) can target it by name.
|
||
|---|---|---|
| .github/workflows | ||
| .sisyphus | ||
| docs | ||
| packages | ||
| scripts | ||
| .gitignore | ||
| eslint.config.js | ||
| lefthook.yml | ||
| LICENSE | ||
| package.json | ||
| playwright.config.ts | ||
| README.md | ||
| tsconfig.base.json | ||
| tsconfig.json | ||
| vitest.workspace.ts | ||
@paratype
A Doorenbos-style Rete II rules engine for TypeScript games, with an authoritative WebSocket chess demo.
Packages
packages/rete— Rete II engine corepackages/chess— Browser chess demo (React + Vite)packages/server— Authoritative Bun WebSocket server
Docs
- SPEC.md — Engine specification
- PHASES.md — Development phases & perf budgets
- RULES.md — Chess rule presets
- PROTOCOL.md — WebSocket message protocol
Getting Started
bun install && bun run check