@memberjunction/ng-composer
Generic message-composer components for MemberJunction Angular applications — the mention editor, its autocomplete dropdown, and the send-button input box wrapper. Extracted from @memberjunction/ng-conversations so lower-level packages (e.g. @memberjunction/ng-user-routines) can embed the composer without depending on the full conversations stack (ng-conversations itself depends on ng-user-routines, so the composer must live below both).
The composer ships ZERO AI knowledge. Mention/command triggers are pluggable: without any trigger providers the editor is a plain text editor with attachments. The AI-aware providers (’@’ agents, ’#’ entities/queries, ’/’ skills) live in @memberjunction/ng-conversations.
Components
Section titled “Components”| Selector | Class | Purpose |
|---|---|---|
mj-mention-editor | MentionEditorComponent | ContentEditable editor with Slack/Teams-style mention chips, attachment support (paste / drag-drop / picker), and ControlValueAccessor ([(ngModel)] works) |
mj-mention-dropdown | MentionDropdownComponent | Keyboard-navigable autocomplete dropdown for mention suggestions |
mj-message-input-box | MessageInputBoxComponent | Presentational wrapper around the mention editor adding the send button (+ optional voice / plan-mode buttons) |
Plus the trigger-provider contract (ComposerTriggerProvider, ComposerSuggestionRequest, DiscoverComposerTriggerProviders) and the exported types MentionSuggestion, MentionSuggestionPreset, and PendingAttachment.
Pluggable triggers — the ComposerTriggerProvider contract
Section titled “Pluggable triggers — the ComposerTriggerProvider contract”Each provider owns ONE trigger character and supplies the suggestions shown while the user types after it:
export abstract class ComposerTriggerProvider { public abstract readonly TriggerChar: string; // e.g. '@' public abstract readonly Key: string; // stable id, e.g. 'agent-mentions' public readonly Priority: number = 0; // higher first when chars collide public abstract GetSuggestions(request: ComposerSuggestionRequest): Promise<MentionSuggestion[]>; public async Initialize(contextUser: UserInfo | null): Promise<void> { /* optional warm-up */ }}Suggestions are generic (type is an open string; optional icon / color / imageUrl drive chip + dropdown cosmetics). A suggestion may carry presets — when there are 2+ the inserted chip renders a preset picker and the selection travels with the chip (data-preset-id / data-preset-name, surviving getPlainTextWithJsonMentions() serialization).
Two ways to supply providers
Section titled “Two ways to supply providers”- Explicit mode — bind instances; exactly this list is active (wins over discovery):
<mj-mention-editor [TriggerProviders]="myProviders" ...></mj-mention-editor>
- Discovery mode (default,
TriggerProvidersunbound) — the editor resolves every ClassFactory registration ofComposerTriggerProvider:Hosts opt individual triggers out by stable key:@RegisterClass(ComposerTriggerProvider, 'agent-mentions')export class AgentMentionProvider extends ComposerTriggerProvider { ... }With no providers registered, the editor degrades gracefully to a plain text editor.<mj-mention-editor [ExcludedTriggerKeys]="['agent-mentions']" ...></mj-mention-editor>
enableMentions (default true) remains the master switch — when false, no providers are consulted at all. MessageInputBoxComponent passes enableMentions / TriggerProviders / ExcludedTriggerKeys / Provider through to the editor.
The AI providers + the mj-ai-composer wrapper
Section titled “The AI providers + the mj-ai-composer wrapper”@memberjunction/ng-conversations registers three plugins (loaded via its LoadComposerPlugins() guard):
| Key | Trigger | Suggests |
|---|---|---|
agent-mentions | @ | Permission-filtered agents (+ configuration presets) and users |
record-mentions | # | Entities the user can read + queries the user can run |
skill-commands | / | Active skills the user can Run |
It also ships <mj-ai-composer> — a wrapper around mj-message-input-box with those plugins built in and the familiar convenience flags EnableAgentMentions / EnableEntityMentions / EnableSkillCommands (all default true). Use it wherever you want the standard AI chat composer; use the raw mj-message-input-box / mj-mention-editor for custom or discovery-driven trigger sets.
<!-- Example: the routine editor — discovery mode, '@' excluded (its agent is fixed by a picker) --><mj-mention-editor [(ngModel)]="InitialMessage" [ExcludedTriggerKeys]="['agent-mentions']" [enableAttachments]="false" [autoFocus]="false" [currentUser]="ProviderToUse.CurrentUser"></mj-mention-editor>Other notable inputs: autoFocus (default true — the chat-composer behavior; set false when embedding in a form), enableAttachments / maxAttachments / maxAttachmentSizeBytes / acceptedFileTypes, placeholder, disabled, Provider (multi-provider hosts; threaded to providers via ComposerSuggestionRequest.Provider).
Value formats
Section titled “Value formats”[(ngModel)]/valueChangecarry the plain-text serialization: mention chips render as@Name(agents/users),#Name(entities/queries), or/Name(skills), quoted when the name contains spaces (e.g.#"Membership Renewals"); line breaks become\n.getPlainTextWithJsonMentions()(used byMessageInputBoxComponent’s send path) encodes each chip as@{"type":"agent","id":"...","name":"...",...}so configuration presets survive persistence.writeValuerenders inbound text as plain text (chips are not re-hydrated from text).
import { ComposerModule } from '@memberjunction/ng-composer';
@NgModule({ imports: [ComposerModule] })export class MyModule {}Consumers
Section titled “Consumers”@memberjunction/ng-conversations— hosts the AI trigger plugins +mj-ai-composer; the chat message composer (message-input, chat area, overlay, workspace)@memberjunction/ng-user-routines— the routine editor’s “Message sent on each run” field (discovery mode,agent-mentionsexcluded)@memberjunction/ng-explorer-core— the Chat resource wrapper@memberjunction/ng-dashboards— Component Studio AI assistant (types only)