Changeset 0.25.1 (#161)

This commit is contained in:
2026-03-08 18:54:53 +00:00
parent 2b01d540d6
commit b3f8b747dd
48 changed files with 531 additions and 888 deletions

View File

@@ -1,8 +1,8 @@
# DESIGN — Surface & Extension Architecture
**Status:** Accepted
**Status:** Accepted (Phases 12 implemented in v0.25.1)
**Scope:** Primitives, Components, Surfaces, Extension hooks, Themes
**Depends on:** v0.22.5 (Go template engine), v0.22.7 (ChatPane)
**Depends on:** v0.22.5 (Go template engine), v0.22.7 (ChatPane), v0.25.1 (audit)
**Informs:** v0.22.8+, EXTENSIONS.md rewrite, ARCHITECTURE.md update, ICD-API, ICD-SURFACE
---
@@ -159,7 +159,9 @@ Primitives.menu({ anchor: el, items: [...], onSelect: fn })
Primitives.dialog({ title: 'Confirm', body: el, onConfirm: fn })
```
Current locations: `ui-primitives.js`, `ui-primitives-additions.js`,
Current locations: `ui-primitives.js` (factory functions, `esc()`,
`createComponentRegistry()`, `componentMixin()`, `showConfirm()`,
`showPrompt()`, `Theme`, `mountAvatarUpload()`)
and Go template components (`model-select.html`, `team-select.html`,
`file-upload.html`). These converge into one coherent set.
@@ -202,23 +204,42 @@ to interact with.
### Instance Pattern
Components use the factory pattern established by ChatPane:
Components use `createComponentRegistry()` and `componentMixin()` from
`ui-primitives.js` for shared lifecycle (instance tracking, event
listener cleanup, destroy):
```js
const pane = ChatPane.create({
messagesEl: document.getElementById('editorChatMessages'),
inputEl: document.getElementById('editorChatInput'),
sendBtnEl: document.getElementById('editorSendBtn'),
channelId: workspaceChatId,
standalone: true,
});
const ChatPane = {
...createComponentRegistry('ChatPane'),
// Lifecycle
pane.renderMessages(msgs);
pane.streamResponse(resp, msgs);
pane.destroy();
create(opts) {
const instance = componentMixin({
id: opts.id || 'pane-' + Date.now(),
messagesEl: opts.messagesEl,
inputEl: opts.inputEl,
channelId: opts.channelId || null,
// ... domain-specific state
// Component-specific teardown (called by mixin's destroy())
_cleanup() {
if (this._cmView) { this._cmView.destroy(); this._cmView = null; }
},
}, ChatPane);
ChatPane._register(instance.id, instance);
return instance;
},
// Custom queries beyond .get(id)
forChannel(channelId) { /* ... */ },
};
```
The mixin provides `_on(el, event, handler)` for tracked event binding
and `destroy()` which calls `_cleanup()` then removes all listeners and
unregisters from the registry. Components that need extra teardown define
`_cleanup()`.
Components can be instantiated multiple times on the same page (editor
has a ChatPane, notes has a ChatPane — independent instances).
@@ -567,7 +588,7 @@ accommodates it without redesign.
b. Register hooks (pre-completion, post-render, etc.)
c. Register surface injections for current surface
d. Initialize tool bridges
5. Surface-specific JS runs (app.js for chat, editor-mode.js, etc.)
5. Surface-specific JS runs (app.js for chat, editor-surface.js, etc.)
```
`Extensions.boot()` replaces the current chat-specific
@@ -672,8 +693,8 @@ post-render hooks use to discover display content from any extension.
| Current State | Target State |
|---------------|-------------|
| `ui-primitives.js` + `ui-primitives-additions.js` | Primitive catalog with stable factory API |
| `ChatPane.create()` (v0.22.7) | Component catalog with shared instance pattern |
| `ui-primitives.js` (merged, with `esc()`, `createComponentRegistry()`, `componentMixin()`) | ✅ Done (v0.25.1) |
| `ChatPane.create()` + 5 other components using shared mixin | ✅ Done (v0.25.1) |
| 5 Go template routes | Surface registry (hardcoded core, manifest-driven extensions) |
| `ctx.ui.replace()` / `ctx.ui.inject()` | Hook 6: Surface Injection with declared mount points |
| `ctx.surfaces.register()` | Manifest `surfaces` field → page engine route registration |
@@ -688,17 +709,22 @@ post-render hooks use to discover display content from any extension.
This does not prescribe version numbers. It describes dependency order.
**Phase 1: Primitive consolidation**
- Audit `ui-primitives.js`, `ui-primitives-additions.js`, and Go
template components
- Define the primitive catalog and factory API
- Define the CSS custom property contract (theme API)
- Migrate existing callers to the consolidated API
**Phase 1: Primitive consolidation** ✅ (v0.25.1)
- `ui-primitives-additions.js` deleted, survivors merged into
`ui-primitives.js`
- `esc()` centralized (13 private copies eliminated)
- Badge system unified (24 scattered classes → grouped in primitives.css)
- CSS variable names normalized, duplicate selectors resolved
- `showConfirm()` is the sole confirm pattern (bare `confirm()` purged)
**Phase 2: Component formalization**
- ChatPane already exists (v0.22.7). Formalize the instance pattern.
- Extract NoteEditor, FileTree, ModelSelector as components
- Each component gets a Go template partial + JS hydration
**Phase 2: Component formalization** ✅ (v0.25.1)
- `createComponentRegistry()` + `componentMixin()` extracted
- 6 components (ChatPane, ModelSelector, UserMenu, CodeEditor, FileTree,
NoteEditor) use the shared mixin. ~100 lines of boilerplate eliminated.
- Each component has a Go template partial + JS hydration
- `surface-nav.js` deleted; navigation is native in `ui-core.js`
- Vendor scripts (`marked.min.js`, `purify.min.js`) and `ui-format.js`
moved to `base.html` (loaded once, available to all surfaces)
**Phase 3: Extension hooks**
- `Extensions.boot()` on every surface (v0.22.8)