# PD rockets PD rockets is a collection of vendorable components built with [Rocket](https://data-star.dev/reference/rocket), Datastar's open-source web component API. Drag-and-drop is the first family: a multi-list drag group, Kanban, sortable-list, bento-grid and file-tree surfaces are working examples, alongside a contextual action menu. A server renders light DOM; Rocket owns browser interaction and emits semantic events; the page connects those events to its Datastar actions and backend handlers. - `contracts/` — DOM inputs, keyboard defaults, and semantic event outputs. - `core/` — pointer lifecycle, drag preview, and FLIP mechanics. - `rocket/` — custom-element lifecycle and domain-specific target geometry. - `examples/hono-datastar/` — JSX event bindings and a local DOM demo. - `examples/go/` — Go templates, Datastar actions, and SSE morphs. - `site/` — a static guide and live examples backed by an in-browser SSE fixture. `rocket-drag-group` coordinates multiple `[data-drop-list]` regions containing `[data-drag-item]` elements. Pointer dragging or Alt + arrows (or h/j/k/l) emits `rocket-drag-group-move` with `{ itemId, fromList, toList, before }`; releasing Alt commits a keyboard move, and Escape cancels it. Groups are independent. Kanban keeps its own column and card contract while sharing the insertion and pointer mechanics. `rocket-context-menu` is a template-first, backend-neutral action menu. Server-rendered items and nested submenus are cloned on open with a target `contextId`; the menu handles popover placement, keyboard navigation, and focus return, then emits `{ action, contextId }`. The page owns action handling and may morph the template with fresh server HTML. For fetched menu fragments, render a direct child marked `data-rocket-menu-content` instead of a template and call `openFor(trigger)` after the page installs the fragment. `closeMenu(refocus?)` and `isOpen()` expose the lifecycle; `rocket-menu-scope` emits `{ root, active }` for page-owned keyboard scopes. Live content remains in the DOM on close. `rocket-inline-edit` owns a title's double-press detection, Enter/blur commit, and Escape cancellation while the page owns its input, edit mode, validation and save. Mark title and input with `data-inline-edit-trigger` / `data-inline-edit-value` and `data-inline-edit-input`; the host emits request, commit and cancel events with an opaque `contextId`. `rocket-bento-workspace` is an experimental two-grid dashboard surface. It reuses the pointer and FLIP lifecycle, but uses cell coordinates and spans instead of list insertion targets. It calculates a transient, animated layout and emits all changed positions on move or resize. The backend applies those positions and returns the confirmed HTML; the guide's in-browser SSE fixture demonstrates that handoff without duplicating placement logic. The consuming page provides CSS Grid tracks (`grid-template-columns` and a fixed `grid-auto-rows`) for pointer-to-cell geometry. `core/board-geometry.ts` provides board-specific lane/grid-track hit testing and remove-then-insert ordering for variable-height cards. `core/board-projection.ts` calculates disposable CSS placement overrides for held or staged cards. These pure helpers do not read application state or move DOM nodes; a consuming board supplies its own move lifecycle and places the generated rules after server-rendered layout styles. Multiple boards can pass a trusted host selector to scope the rules. Linear lists continue to use `core/insertion-target.ts`. `installBoardProjection()` is the browser half: the page supplies current holds and an optional staged preview through callbacks. It reasserts only those cards across full morphs, marking persistence state, moving held cards between lanes when CSS alone cannot, and keeping its override style after server truth and outside a morph region if the page placed it there. Request dispatch, confirmation, and retry policy stay with the page. `installBoardDrag()` supplies lane-grid pointer capture, keep-in-place previews, hit testing and a morph-tolerant drag lifecycle. Cards use `data-board-card`, lanes use `data-board-lane` / `data-col`, and the explicit grip uses `data-rocket-board-drag-handle`. A direct child `