--- title: Composer state description: One isolated store per Composer, with explicit createStore handles for cross-tree access. --- The composer's state — editor content, command lists, ask-user flow, attachments — lives in a store. Every `` creates its own isolated instance, so a single composer works with zero setup and several composers coexist on one page without any wiring. ## Resolution `Composer` resolves its store once, at mount: 1. an explicit `store` prop — a `Composer.createStore()` handle, else 2. an instance created for this mount, owned by it and reset on unmount. ```tsx // Zero config — an isolated instance. Two of these never interact. {/* … */} // Explicit — a handle you own, for anything that must reach the // composer from outside its tree. const composerStore = Composer.createStore(); {/* … */} ``` ## Reading state inside the tree `useComposer(selector)` subscribes to a slice of the nearest composer's store. It throws outside a `` — inside the tree, no store is ever named: ```ts const isSubmitting = useComposer((state) => state.isSubmitting); const attachments = useComposer((state) => state.attachments.items); ``` `useComposerController()` is its imperative twin — the nearest composer's editor controls (focus, insert, clear) for components inside the form. ## Reaching in from outside A `Composer.createStore()` handle carries the full surface. Imperative control needs no hook at all: ```ts composerStore.controller.insertChip({ prefix: "@", value: fileId, label: fileName }); composerStore.controller.focus(); ``` Reactive reads go through `useComposerStore(store, selector)` — the outside-the-tree twin of `useComposer`: ```ts const attachments = useComposerStore(composerStore, (state) => state.attachments.items); ``` Wrap it once per instance so call sites pass only the selector: ```ts // lib/composer.ts — one module owns the instance export const chatComposerStore = Composer.createStore(); export const useChatComposer = (selector: (state: ComposerState) => T) => useComposerStore(chatComposerStore, selector); ``` The rule is deliberate: **explicit at the boundary, implicit within it**. Inside ``, hooks resolve by context and nothing is named; outside it, someone must say which composer they mean. There is no global fallback — a composer's state can never be read or driven by accident.