@aparte/react 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,19 @@
1
1
  import React from 'react';
2
- import { type AparteConfigClass, type AparteChatImperativeApi } from '@aparte/core';
2
+ import { type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';
3
3
  import type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';
4
4
  export interface AparteChatProps {
5
+ /**
6
+ * The host element's `id`, and therefore the `targetId` every event this chat
7
+ * dispatches carries.
8
+ *
9
+ * Generated when omitted, which is the right default — but it used to be
10
+ * generated and neither accepted nor exposed, so
11
+ * `AparteClientOptions.scopeToTargetId` (the documented way to run several
12
+ * independent clients on one page) was unreachable from this component: there
13
+ * was no way to learn the id the client had to match. Angular exposed it; React,
14
+ * Vue and Svelte did not.
15
+ */
16
+ id?: string;
5
17
  /**
6
18
  * Messages on the active path. **Optional** — omit for an uncontrolled chat
7
19
  * that starts empty (defaults to `[]`); pass it together with
@@ -37,7 +49,7 @@ export interface AparteChatProps {
37
49
  attachments?: boolean;
38
50
  /**
39
51
  * Active conversation id. When set, the wrapper loads/persists via the
40
- * `ConversationManager` registered in `AparteConfig` (set `null` to deselect).
52
+ * `AparteConversationManager` registered in `aparteGlobalConfig` (set `null` to deselect).
41
53
  */
42
54
  conversationId?: string | null;
43
55
  /**
@@ -105,7 +117,7 @@ export interface AparteChatProps {
105
117
  onMessageSent?: (event: AparteSendEventDetail) => void;
106
118
  /**
107
119
  * Fired when a custom bubble action (registered via
108
- * `AparteConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed
120
+ * `aparteGlobalConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed
109
121
  * wrapper over the bubbling `aparte-action` DOM event. Dispatch on `detail.actionId`.
110
122
  */
111
123
  onAction?: (detail: AparteActionEventDetail) => void;
@@ -121,18 +133,13 @@ export interface AparteChatProps {
121
133
  /** Fired when the controller lazily creates a conversation on first send. */
122
134
  onConversationCreated?: (id: string) => void;
123
135
  /**
124
- * Instance {@link AparteConfigClass} for this chat. When set, every aparté
136
+ * Instance {@link AparteConfig} for this chat. When set, every aparté
125
137
  * component rendered inside resolves THIS config instead of the global
126
- * `AparteConfig` singleton — letting several independently-configured chats
138
+ * `aparteGlobalConfig` — letting several independently-configured chats
127
139
  * (different providers, tools, renderers) coexist on one page. Omit for the
128
140
  * global config. Read once when the host mounts.
129
141
  */
130
- config?: AparteConfigClass;
142
+ config?: AparteConfig;
131
143
  }
132
- /**
133
- * The React ref handle for `<AparteChat>` — the canonical imperative surface
134
- * shared by all four wrappers (see `AparteChatImperativeApi` in `@aparte/core`).
135
- */
136
- export type AparteChatHandle = AparteChatImperativeApi;
137
144
  export declare const AparteChat: React.ForwardRefExoticComponent<AparteChatProps & React.RefAttributes<AparteChatImperativeApi>>;
138
145
  //# sourceMappingURL=AparteChat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AparteChat.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.tsx"],"names":[],"mappings":"AAEA,OAAO,KAON,MAAM,OAAO,CAAC;AACf,OAAO,EAA+D,KAAK,iBAAiB,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACjJ,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEjG,MAAM,WAAW,eAAe;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IACvD,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,gEAAgE;IAChE,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,6EAA6E;IAC7E,qBAAqB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAE7C;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEvD,eAAO,MAAM,UAAU,iGAuNrB,CAAC"}
1
+ {"version":3,"file":"AparteChat.d.ts","sourceRoot":"","sources":["../../src/components/AparteChat.tsx"],"names":[],"mappings":"AAEA,OAAO,KAON,MAAM,OAAO,CAAC;AACf,OAAO,EAA+D,KAAK,YAAY,EAAE,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5I,OAAO,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAEjG,MAAM,WAAW,eAAe;IAC5B;;;;;;;;;;OAUG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACrD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;IACvD,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IACrD,gEAAgE;IAChE,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,6EAA6E;IAC7E,qBAAqB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAE7C;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACzB;AAED,eAAO,MAAM,UAAU,iGA0NrB,CAAC"}
@@ -7,7 +7,7 @@ export interface AparteUiProps {
7
7
  onElementEvent?: (event: CustomEvent) => void;
8
8
  /**
9
9
  * Which custom events to forward through `onElementEvent`. Defaults to the
10
- * interactive aparté surface ({@link DEFAULT_UI_EVENTS}); pass your own list to
10
+ * interactive aparté surface ({@link APARTE_DEFAULT_UI_EVENTS}); pass your own list to
11
11
  * listen to other events (e.g. `['aparte-composer-change']` for attachments).
12
12
  */
13
13
  events?: string[];
@@ -21,6 +21,11 @@ export interface AparteUiHandle {
21
21
  * you don't need a dedicated React wrapper per element. React equivalent of
22
22
  * Angular's `AparteUiComponent`.
23
23
  *
24
+ * `name` can be any custom element, including one of yours. `aparte-model-selector`
25
+ * below is defined by `@aparte/plugin-model-selector`, not by core — until that
26
+ * package is imported the tag mounts empty and inert with no error, and upgrades on
27
+ * its own once the definition arrives (which is what makes lazy-loading it work).
28
+ *
24
29
  * @example
25
30
  * <AparteUi name="aparte-model-selector" props={{ placeholder: 'Ask…', '--glow-speed': '4s' }} onElementEvent={onEvent} />
26
31
  */
@@ -1 +1 @@
1
- {"version":3,"file":"AparteUi.d.ts","sourceRoot":"","sources":["../../src/components/AparteUi.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,wEAAwE;IACxE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,UAAU,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;CACtF;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,0GAgDnB,CAAC"}
1
+ {"version":3,"file":"AparteUi.d.ts","sourceRoot":"","sources":["../../src/components/AparteUi.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC1B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,wEAAwE;IACxE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC9C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,UAAU,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,SAAS,CAAC;CACtF;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,0GAgDnB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { AparteMessage, AparteSegment } from '../types.js';
2
- import type { AparteChatHandle } from '../components/AparteChat.js';
2
+ import type { AparteChatImperativeApi } from '@aparte/core';
3
3
  /**
4
4
  * Idiomatic React ergonomics for `<AparteChat>`. Owns the `messages` state and
5
5
  * the component ref so the consumer doesn't have to wire `onMessagesChange`
@@ -20,7 +20,7 @@ import type { AparteChatHandle } from '../components/AparteChat.js';
20
20
  export interface UseAparteChat {
21
21
  messages: AparteMessage[];
22
22
  setMessages: React.Dispatch<React.SetStateAction<AparteMessage[]>>;
23
- ref: React.RefObject<AparteChatHandle>;
23
+ ref: React.RefObject<AparteChatImperativeApi>;
24
24
  appendMessage: (message: AparteMessage) => void;
25
25
  updateMessage: (messageId: string, updates: Partial<AparteMessage>) => void;
26
26
  updateLastMessage: (content: string, options?: {
@@ -1 +1 @@
1
- {"version":3,"file":"useAparteChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useAparteChat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAEpE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAKnE,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAEvC,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAC5E,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAC5E,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5E,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,sBAAsB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,WAAW,EAAE,MAAM,OAAO,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,aAAa,EAAO,GAAG,aAAa,CAyB1E"}
1
+ {"version":3,"file":"useAparteChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useAparteChat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAE5D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAKnE,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;IAE9C,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAC5E,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,UAAU,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAC5E,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,MAAM,GAAG,IAAI,CAAC;IAC5E,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,sBAAsB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvF,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,WAAW,EAAE,MAAM,OAAO,CAAC;CAC9B;AAED,wBAAgB,aAAa,CAAC,OAAO,GAAE,aAAa,EAAO,GAAG,aAAa,CAyB1E"}
@@ -18,7 +18,7 @@ export interface UseConversationManager {
18
18
  unarchive: (id: string) => Promise<void>;
19
19
  }
20
20
  /**
21
- * React-state wrapper around the core `ConversationManager`. The active
21
+ * React-state wrapper around the core `AparteConversationManager`. The active
22
22
  * conversation is owned by the chat component's controller; switch by binding
23
23
  * `conversationId` on `<AparteChat>`. React equivalent of Angular's
24
24
  * `ConversationManagerService`.
@@ -1 +1 @@
1
- {"version":3,"file":"useConversationManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useConversationManager.ts"],"names":[],"mappings":"AACA,OAAO,EAGH,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACnC,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,0CAA0C;IAC1C,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,4CAA4C;IAC5C,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC9C,qDAAqD;IACrD,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3D,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,sBAAsB,CAsD/D"}
1
+ {"version":3,"file":"useConversationManager.d.ts","sourceRoot":"","sources":["../../src/hooks/useConversationManager.ts"],"names":[],"mappings":"AACA,OAAO,EAIH,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACnC,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,0CAA0C;IAC1C,mBAAmB,EAAE,kBAAkB,EAAE,CAAC;IAC1C,4CAA4C;IAC5C,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;IAC5C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kBAAkB,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC9C,qDAAqD;IACrD,IAAI,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,SAAS,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3D,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI,sBAAsB,CA+D/D"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,8 @@
3
3
  * React 18/19 integration with hooks and segment support.
4
4
  */
5
5
  export { AparteChat } from './components/AparteChat.js';
6
- export type { AparteChatProps, AparteChatHandle } from './components/AparteChat.js';
6
+ export type { AparteChatProps } from './components/AparteChat.js';
7
+ export type { AparteChatImperativeApi } from '@aparte/core';
7
8
  export { useAparteChat } from './hooks/useAparteChat.js';
8
9
  export type { UseAparteChat } from './hooks/useAparteChat.js';
9
10
  export { useAparteClient } from './hooks/useAparteClient.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGpF,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,YAAY,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE9E,YAAY,EACR,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACxB,MAAM,YAAY,CAAC;AASpB,UAAU,uBAAuB;IAE7B,sBAAsB,EAAE,GAAG,CAAC;IAE5B,oBAAoB,EAAE,GAAG,CAAC;IAE1B,oBAAoB,EAAE,GAAG,CAAC;IAE1B,iBAAiB,EAAE,GAAG,CAAC;IAEvB,6BAA6B,EAAE,GAAG,CAAC;IAEnC,gCAAgC,EAAE,GAAG,CAAC;IAEtC,uBAAuB,EAAE,GAAG,CAAC;IAE7B,sBAAsB,EAAE,GAAG,CAAC;IAE5B,yBAAyB,EAAE,GAAG,CAAC;CAClC;AAED,OAAO,CAAC,MAAM,CAAC;IAEX,UAAU,GAAG,CAAC;QAEV,UAAU,iBAAkB,SAAQ,uBAAuB;SAAG;KACjE;CACJ;AAED,OAAO,QAAQ,OAAO,CAAC;IAEnB,UAAU,GAAG,CAAC;QAEV,UAAU,iBAAkB,SAAQ,uBAAuB;SAAG;KACjE;CACJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAKlE,YAAY,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG9D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,YAAY,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE9E,YAAY,EACR,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,GACxB,MAAM,YAAY,CAAC;AASpB,UAAU,uBAAuB;IAE7B,sBAAsB,EAAE,GAAG,CAAC;IAE5B,oBAAoB,EAAE,GAAG,CAAC;IAE1B,oBAAoB,EAAE,GAAG,CAAC;IAE1B,iBAAiB,EAAE,GAAG,CAAC;IAEvB,6BAA6B,EAAE,GAAG,CAAC;IAEnC,gCAAgC,EAAE,GAAG,CAAC;IAEtC,uBAAuB,EAAE,GAAG,CAAC;IAE7B,sBAAsB,EAAE,GAAG,CAAC;IAE5B,yBAAyB,EAAE,GAAG,CAAC;CAClC;AAED,OAAO,CAAC,MAAM,CAAC;IAEX,UAAU,GAAG,CAAC;QACV,UAAU,iBAAkB,SAAQ,uBAAuB;SAAG;KACjE;CACJ;AAED,OAAO,QAAQ,OAAO,CAAC;IAEnB,UAAU,GAAG,CAAC;QACV,UAAU,iBAAkB,SAAQ,uBAAuB;SAAG;KACjE;CACJ"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import React, { forwardRef, useId, useRef, useState, useEffect, useImperativeHandle, useCallback, useMemo } from "react";
3
- import { AparteChatHost, isAwaitingReply, AparteClient, ConversationManager, AparteConfig, DEFAULT_UI_EVENTS, applyElementProps } from "@aparte/core";
3
+ import { AparteChatHost, isAwaitingReply, AparteClient, aparteGlobalConfig, AparteConversationManager, APARTE_DEFAULT_UI_EVENTS, applyElementProps } from "@aparte/core";
4
4
  const AparteChat = forwardRef(function AparteChat2({
5
5
  messages = [],
6
6
  placeholder = "Type a message...",
@@ -23,9 +23,11 @@ const AparteChat = forwardRef(function AparteChat2({
23
23
  onMessagesChange,
24
24
  onMessageAppended,
25
25
  onTypingChange,
26
- onConversationCreated
26
+ onConversationCreated,
27
+ id: providedId
27
28
  }, ref) {
28
- const hostId = `aparte-chat-${useId().replace(/:/g, "")}`;
29
+ const generatedId = `aparte-chat-${useId().replace(/:/g, "")}`;
30
+ const hostId = providedId ?? generatedId;
29
31
  const hostElRef = useRef(null);
30
32
  const viewportRef = useRef(null);
31
33
  const composerRef = useRef(null);
@@ -226,8 +228,8 @@ function useConversationManager() {
226
228
  const [conversations, setConversations] = useState([]);
227
229
  const [activeId, setActiveId] = useState(null);
228
230
  useEffect(() => () => unsubRef.current?.(), []);
229
- const init = useCallback(async (adapter) => {
230
- const m = new ConversationManager(adapter);
231
+ const init = useCallback(async (adapter, config = aparteGlobalConfig) => {
232
+ const m = new AparteConversationManager(adapter);
231
233
  managerRef.current = m;
232
234
  unsubRef.current = m.subscribe((convs) => {
233
235
  setConversations([...convs]);
@@ -235,7 +237,7 @@ function useConversationManager() {
235
237
  });
236
238
  await m.init();
237
239
  setActiveId(m.activeId);
238
- AparteConfig.setConversationManager(m);
240
+ config.setConversationManager(m);
239
241
  }, []);
240
242
  const assert = () => {
241
243
  if (!managerRef.current) {
@@ -275,7 +277,7 @@ const AparteUi = forwardRef(function AparteUi2({ name, props = {}, onElementEven
275
277
  const elRef = useRef(null);
276
278
  const cbRef = useRef(onElementEvent);
277
279
  cbRef.current = onElementEvent;
278
- const evts = events ?? DEFAULT_UI_EVENTS;
280
+ const evts = events ?? APARTE_DEFAULT_UI_EVENTS;
279
281
  const evtsKey = evts.join("|");
280
282
  useEffect(() => {
281
283
  const host = hostRef.current;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/components/AparteChat.tsx","../src/hooks/useAparteChat.ts","../src/hooks/useAparteClient.ts","../src/hooks/useConversationManager.ts","../src/components/AparteUi.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n useEffect,\n useId,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport { AparteChatHost, isAwaitingReply, type AparteChatHostBinding, type AparteConfigClass, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\nexport interface AparteChatProps {\n /**\n * Messages on the active path. **Optional** — omit for an uncontrolled chat\n * that starts empty (defaults to `[]`); pass it together with\n * `onMessagesChange` to control the list from the parent.\n */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: while the message\n * list is empty the composer sits vertically centered with the `emptyState`\n * content above it, then slides to the bottom on the first message (~0.3s).\n * Off by default — purely additive: adds the `aparte-chat-container--auto-center`\n * modifier + a `data-aparte-empty` attribute that the shipped `aparte.css` recipe\n * keys off. No effect unless you also render an `emptyState`.\n */\n centerWhenEmpty?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` in `onMessageSent` — otherwise the\n * file the user deliberately attached is dropped in silence. No effect when you\n * pass your own `composer` (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Active conversation id. When set, the wrapper loads/persists via the\n * `ConversationManager` registered in `AparteConfig` (set `null` to deselect).\n */\n conversationId?: string | null;\n /**\n * Custom composer content, rendered inside `<aparte-composer>` in place of the\n * default shell (input · send, plus the attachment primitives when\n * `attachments` is set). Compose the headless\n * `aparte-composer-*` primitives freely — e.g. a skin-specific layout. Omit for\n * the default shell. The `<aparte-composer>` element (and its placeholder /\n * disabled / submit-on-enter behaviour) is always provided by the wrapper.\n */\n composer?: React.ReactNode;\n /**\n * Render your OWN element per message in place of `<aparte-chat-bubble>`.\n * Opt-in — omit for the default bubble. The returned node is driven by the\n * reactive message list, so it updates live during streaming (no need to\n * implement any imperative interface): re-render from `message.content` /\n * `message.segments`. Note the built-in action bar (retry/edit/branch) and\n * the imperative streaming push are the native bubble's — a custom bubble\n * owns whatever it wires (it can dispatch `aparte-retry` etc. or call the\n * wrapper's imperative API).\n */\n renderBubble?: (message: AparteMessage) => React.ReactNode;\n /**\n * Welcome / placeholder content shown INSIDE the viewport while there are no\n * messages (a real \"empty state\" region, not a workaround via `aboveComposer`).\n * Replaced by the message list on the first message.\n */\n emptyState?: React.ReactNode;\n /**\n * Content rendered ABOVE the composer (e.g. a disclaimer banner, a\n * \"scroll to bottom\" affordance, a context chip). Ignored when a full\n * custom `composer` replaces the shell.\n */\n aboveComposer?: React.ReactNode;\n /**\n * The composer's bottom row — a mode picker, a model selector, a token counter.\n * Rendered inside core's `<aparte-composer-toolbar>`; nothing is rendered at all\n * when you pass nothing, so an unused row never draws its separator.\n *\n * **Placement is the DOM order.** There is no left/center/right slot: put things in\n * the order you want them, and push a control (with everything after it) to the end\n * with `margin-inline-start: auto`. That is a logical property, so the row reads\n * correctly in a right-to-left locale with no extra work.\n *\n * Ignored when a full custom `composer` replaces the shell.\n *\n * @example\n * <AparteChat\n * messages={messages}\n * onMessagesChange={setMessages}\n * toolbar={<>\n * <ModePicker value={mode} onChange={setMode} />\n * <ModelSelector style={{ marginInlineStart: 'auto' }} />\n * </>}\n * />\n */\n toolbar?: React.ReactNode;\n\n /**\n * Notification that the user submitted a message from the composer. The\n * user's message is **appended to the thread automatically** (optimistic UI)\n * before this fires — do NOT add it again here. In an uncontrolled chat,\n * appending it duplicates it; in a controlled chat, mirror it into your own\n * `messages`. Use this for side-effects: scroll, analytics, backend send.\n */\n onMessageSent?: (event: AparteSendEventDetail) => void;\n /**\n * Fired when a custom bubble action (registered via\n * `AparteConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed\n * wrapper over the bubbling `aparte-action` DOM event. Dispatch on `detail.actionId`.\n */\n onAction?: (detail: AparteActionEventDetail) => void;\n /**\n * Fired when the active message path changes (branch navigation / edit /\n * retry / streaming). Set the result back as the `messages` prop.\n */\n onMessagesChange?: (messages: AparteMessage[]) => void;\n /** Fired when a message is appended internally (e.g. by AparteClient). */\n onMessageAppended?: (message: AparteMessage) => void;\n /** Fired when the typing/\"thinking\" indicator should toggle. */\n onTypingChange?: (isTyping: boolean) => void;\n /** Fired when the controller lazily creates a conversation on first send. */\n onConversationCreated?: (id: string) => void;\n\n /**\n * Instance {@link AparteConfigClass} for this chat. When set, every aparté\n * component rendered inside resolves THIS config instead of the global\n * `AparteConfig` singleton — letting several independently-configured chats\n * (different providers, tools, renderers) coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfigClass;\n}\n\n/**\n * The React ref handle for `<AparteChat>` — the canonical imperative surface\n * shared by all four wrappers (see `AparteChatImperativeApi` in `@aparte/core`).\n */\nexport type AparteChatHandle = AparteChatImperativeApi;\n\nexport const AparteChat = forwardRef<AparteChatHandle, AparteChatProps>(function AparteChat(\n {\n messages = [],\n placeholder = 'Type a message...',\n disabled = false,\n isTyping = false,\n typingText = 'Assistant is thinking...',\n submitOnEnter = true,\n layoutTransitionMs = 0,\n centerWhenEmpty = false,\n attachments = false,\n conversationId = null,\n composer,\n renderBubble,\n emptyState,\n aboveComposer,\n toolbar,\n config,\n onMessageSent,\n onAction,\n onMessagesChange,\n onMessageAppended,\n onTypingChange,\n onConversationCreated,\n },\n ref,\n) {\n // useId() is SSR-stable (server and client agree), so no hydration mismatch.\n // Strip ':' so the id is also safe in CSS/querySelector, not just getElementById.\n const hostId = `aparte-chat-${useId().replace(/:/g, '')}`;\n const hostElRef = useRef<HTMLDivElement>(null);\n const viewportRef = useRef<HTMLElement>(null);\n const composerRef = useRef<HTMLElement>(null);\n\n // Authoritative message list lives in a ref (the host reads it synchronously);\n // `renderMessages` state drives the declarative bubble list.\n const messagesRef = useRef<AparteMessage[]>(messages);\n const [renderMessages, setRenderMessages] = useState<AparteMessage[]>(messages);\n const [typingActive, setTypingActive] = useState(isTyping);\n const [, setIsStreaming] = useState(false);\n\n const hostRef = useRef<AparteChatHost | null>(null);\n const lastConvRef = useRef<string | null>(conversationId);\n\n // Keep the latest prop callbacks in a ref so the host's stable binding always\n // calls the current handlers without recreating the host.\n const cbRef = useRef({ onMessageSent, onAction, onMessagesChange, onMessageAppended, onTypingChange, onConversationCreated });\n cbRef.current = { onMessageSent, onAction, onMessagesChange, onMessageAppended, onTypingChange, onConversationCreated };\n\n const applyMessages = (m: AparteMessage[]) => {\n messagesRef.current = m;\n setRenderMessages(m);\n };\n\n // Create the host once after mount.\n useEffect(() => {\n const host = hostElRef.current;\n if (!host) return;\n const binding: AparteChatHostBinding = {\n hostId,\n host,\n viewport: viewportRef.current,\n getMessages: () => messagesRef.current,\n setMessages: (m) => applyMessages(m as AparteMessage[]),\n onMessagesChange: (m) => cbRef.current.onMessagesChange?.(m as AparteMessage[]),\n onMessageAppended: (m) => cbRef.current.onMessageAppended?.(m as AparteMessage),\n onTypingChange: (t) => { setTypingActive(t); cbRef.current.onTypingChange?.(t); },\n onStreamingChange: (id) => setIsStreaming(id !== null),\n afterRender: (cb) => { requestAnimationFrame(() => cb()); },\n resetComposer: () => (composerRef.current as unknown as { reset?: () => void })?.reset?.(),\n };\n const h = new AparteChatHost(binding, {\n layoutTransitionMs,\n conversationId: conversationId ?? null,\n onConversationCreated: (id) => cbRef.current.onConversationCreated?.(id),\n config,\n });\n hostRef.current = h;\n const teardown = h.bind();\n return () => { teardown(); hostRef.current = null; };\n // The host is created once per mount (keyed by the stable hostId); prop\n // changes flow through cbRef / dedicated effects, not by recreating it.\n }, [hostId]);\n\n // Parent push: sync the prop into the authoritative list. Guarded by ref\n // identity so the host's own emit→parent→prop round-trip doesn't loop.\n useEffect(() => {\n if (messages === messagesRef.current) return;\n applyMessages(messages);\n if (messages.length === 0) hostRef.current?.clearRenderCache();\n }, [messages]);\n\n // Reconcile bubbles whenever the rendered list changes (the host queries the\n // DOM for `<aparte-chat-bubble message-id>` elements and pushes segments).\n useEffect(() => { hostRef.current?.syncBubbles(); }, [renderMessages]);\n\n // Controlled typing indicator: reflect the prop, while the host may flip it\n // off internally on the first streamed token.\n useEffect(() => { setTypingActive(isTyping); }, [isTyping]);\n\n // Conversation id changes (the initial value is loaded by the host on bind).\n useEffect(() => {\n if (conversationId === lastConvRef.current) return;\n lastConvRef.current = conversationId;\n void hostRef.current?.setConversationId(conversationId ?? null);\n }, [conversationId]);\n\n // Surface composer sends to the consumer (the controller handles the\n // conversation side separately via its own host listener).\n useEffect(() => {\n const composer = composerRef.current;\n if (!composer) return;\n const onSend = (e: Event) => {\n (viewportRef.current as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n cbRef.current.onMessageSent?.((e as CustomEvent<AparteSendEventDetail>).detail);\n };\n composer.addEventListener('aparte-send', onSend);\n return () => composer.removeEventListener('aparte-send', onSend);\n }, []);\n\n // aparte-composer exposes `placeholder`/`disabled` as GETTER-ONLY accessors.\n // React 19 sets matching props as PROPERTIES on custom elements, which throws\n // (\"Cannot set property placeholder ... which has only a getter\"). Set them as\n // attributes imperatively instead (the getter reads the attribute).\n useEffect(() => {\n const composer = composerRef.current;\n if (!composer) return;\n composer.setAttribute('placeholder', placeholder);\n if (disabled) composer.setAttribute('disabled', '');\n else composer.removeAttribute('disabled');\n }, [placeholder, disabled]);\n\n // Custom bubble actions bubble to the host root as `aparte-action`; surface them\n // as a typed prop.\n useEffect(() => {\n const host = hostElRef.current;\n if (!host) return;\n const onAct = (e: Event) => cbRef.current.onAction?.((e as CustomEvent<AparteActionEventDetail>).detail);\n host.addEventListener('aparte-action', onAct);\n return () => host.removeEventListener('aparte-action', onAct);\n }, []);\n\n useImperativeHandle(ref, (): AparteChatHandle => ({\n appendMessage: (m) => hostRef.current?.appendMessage(m),\n updateMessage: (id, u) => hostRef.current?.updateMessage(id, u),\n updateLastMessage: (c, o) => hostRef.current?.updateLastMessage(c, o),\n addSegment: (s) => hostRef.current?.addSegment(s),\n updateSegment: (id, u) => hostRef.current?.updateSegment(id, u),\n removeSegment: (id) => hostRef.current?.removeSegment(id),\n appendToSegment: (id, c) => hostRef.current?.appendToSegment(id, c),\n getMessages: () => hostRef.current?.getMessages() ?? messagesRef.current,\n clearMessages: () => hostRef.current?.clearMessages(),\n addBranch: (id) => hostRef.current?.addBranch(id) ?? 0,\n addSiblingOf: (id, m) => hostRef.current?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id) => hostRef.current?.truncateFrom(id),\n truncateResponsesAfter: (id) => hostRef.current?.truncateResponsesAfter(id),\n injectTokenStream: (id, tokens) => hostRef.current?.streamTokens(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => hostRef.current?.stopTokenStream(),\n setConversationId: (id) => hostRef.current?.setConversationId(id) ?? Promise.resolve(),\n scrollToBottom: () => (viewportRef.current as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.(),\n focusInput: () => (composerRef.current as unknown as { focus?: () => void })?.focus?.(),\n isStreaming: () => hostRef.current?.isStreaming ?? false,\n getViewport: () => viewportRef.current,\n }), []);\n\n return (\n <div\n className={`aparte-chat-container${centerWhenEmpty ? ' aparte-chat-container--auto-center' : ''}`}\n data-aparte-chat=\"\"\n data-aparte-empty={centerWhenEmpty && renderMessages.length === 0 ? '' : undefined}\n id={hostId}\n ref={hostElRef}\n >\n <aparte-chat-viewport ref={viewportRef as React.Ref<HTMLElement>} framework-managed=\"\">\n {renderMessages.length === 0 && emptyState}\n {renderMessages.map((m) => (\n renderBubble\n ? <React.Fragment key={m.id}>{renderBubble(m)}</React.Fragment>\n : (\n <aparte-chat-bubble\n key={m.id}\n message-id={m.id}\n data-role={m.role}\n timestamp={m.timestamp}\n content={m.content}\n streaming={isAwaitingReply(m) ? '' : undefined}\n />\n )\n ))}\n <aparte-chat-status visible={typingActive ? '' : undefined} text={typingText} />\n </aparte-chat-viewport>\n\n {aboveComposer}\n\n <aparte-composer\n ref={composerRef as React.Ref<HTMLElement>}\n target={hostId}\n submit-on-enter={submitOnEnter ? undefined : 'false'}\n >\n {composer ?? (\n <div className=\"aparte-composer-shell\">\n {attachments && <aparte-composer-attachments />}\n <div className=\"aparte-composer-row\">\n {attachments && <aparte-composer-add-attachment />}\n <aparte-composer-input />\n <aparte-composer-send />\n </div>\n {toolbar != null && (\n <aparte-composer-toolbar>{toolbar}</aparte-composer-toolbar>\n )}\n </div>\n )}\n </aparte-composer>\n </div>\n );\n});\n\nAparteChat.displayName = 'AparteChat';\n","import { useRef, useState } from 'react';\nimport type { AparteMessage, AparteSegment } from '../types.js';\nimport type { AparteChatHandle } from '../components/AparteChat.js';\n\n/**\n * Idiomatic React ergonomics for `<AparteChat>`. Owns the `messages` state and\n * the component ref so the consumer doesn't have to wire `onMessagesChange`\n * back into `messages` by hand. Spread `ref` + `messages` + `onMessagesChange`\n * onto `<AparteChat>` and drive it with the returned imperative helpers.\n *\n * @example\n * const chat = useAparteChat();\n * return (\n * <AparteChat\n * ref={chat.ref}\n * messages={chat.messages}\n * onMessagesChange={chat.setMessages}\n * />\n * );\n * // The user's message is appended automatically on send — don't re-add it.\n */\nexport interface UseAparteChat {\n messages: AparteMessage[];\n setMessages: React.Dispatch<React.SetStateAction<AparteMessage[]>>;\n // Typed to match `<AparteChat>`'s forwardRef target so `ref={chat.ref}`\n // typechecks verbatim — @types/react 18.3's variance rejects the\n // useRef(null) `RefObject<T | null>` shape against `Ref<T>`, so the (safe)\n // cast lives here once, not in every consumer.\n ref: React.RefObject<AparteChatHandle>;\n // ── imperative helpers (delegate to the component handle) ──\n appendMessage: (message: AparteMessage) => void;\n updateMessage: (messageId: string, updates: Partial<AparteMessage>) => void;\n updateLastMessage: (content: string, options?: { append?: boolean }) => void;\n addSegment: (segment: AparteSegment) => void;\n updateSegment: (segmentId: string, updates: Partial<AparteSegment>) => void;\n removeSegment: (segmentId: string) => void;\n appendToSegment: (segmentId: string, content: string) => void;\n clearMessages: () => void;\n addBranch: (messageId: string) => number;\n addSiblingOf: (existingId: string, message: AparteMessage) => string | null;\n truncateFrom: (messageId: string) => void;\n truncateResponsesAfter: (userMessageId: string) => void;\n injectTokenStream: (messageId: string, tokens: AsyncIterable<string>) => Promise<void>;\n stopTokenStream: () => void;\n setConversationId: (id: string | null) => Promise<void>;\n isStreaming: () => boolean;\n}\n\nexport function useAparteChat(initial: AparteMessage[] = []): UseAparteChat {\n const [messages, setMessages] = useState<AparteMessage[]>(initial);\n const ref = useRef<AparteChatHandle | null>(null);\n const h = () => ref.current;\n return {\n messages,\n setMessages,\n ref: ref as React.RefObject<AparteChatHandle>,\n appendMessage: (m) => h()?.appendMessage(m),\n updateMessage: (id, u) => h()?.updateMessage(id, u),\n updateLastMessage: (c, o) => h()?.updateLastMessage(c, o),\n addSegment: (s) => h()?.addSegment(s),\n updateSegment: (id, u) => h()?.updateSegment(id, u),\n removeSegment: (id) => h()?.removeSegment(id),\n appendToSegment: (id, c) => h()?.appendToSegment(id, c),\n clearMessages: () => h()?.clearMessages(),\n addBranch: (id) => h()?.addBranch(id) ?? 0,\n addSiblingOf: (id, m) => h()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id) => h()?.truncateFrom(id),\n truncateResponsesAfter: (id) => h()?.truncateResponsesAfter(id),\n injectTokenStream: (id, tokens) => h()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => h()?.stopTokenStream(),\n setConversationId: (id) => h()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => h()?.isStreaming() ?? false,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\nexport interface UseAparteClient {\n /** The underlying agnostic client. */\n client: AparteClient;\n /** Abort the current AI response + all active tool calls. */\n abort: () => void;\n}\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts listening on mount, stops on unmount. React equivalent of\n * Angular's `AparteAiService`.\n *\n * @example\n * const { abort } = useAparteClient({ keyResolver });\n */\nexport function useAparteClient(options?: AparteClientOptions): UseAparteClient {\n const ref = useRef<AparteClient | null>(null);\n if (!ref.current) ref.current = new AparteClient(options ?? {});\n useEffect(() => {\n const c = ref.current as AparteClient;\n c.start();\n return () => c.stop();\n }, []);\n return { client: ref.current, abort: () => ref.current?.abort() };\n}\n","import { useEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport {\n AparteConfig,\n ConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\nexport interface UseConversationManager {\n conversations: AparteConversation[];\n /** Active conversations, newest first. */\n activeConversations: AparteConversation[];\n /** Archived conversations, newest first. */\n archivedConversations: AparteConversation[];\n activeId: string | null;\n activeConversation: AparteConversation | null;\n /** Initialise with a storage adapter (call once). */\n init: (adapter: AparteStorageAdapter) => Promise<void>;\n createNew: (title?: string) => Promise<AparteConversation>;\n addMessage: (convId: string, message: AparteMessage) => Promise<void>;\n updateMessages: (convId: string, messages: AparteMessage[]) => Promise<void>;\n delete: (id: string) => Promise<void>;\n archive: (id: string) => Promise<void>;\n unarchive: (id: string) => Promise<void>;\n}\n\n/**\n * React-state wrapper around the core `ConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. React equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager(): UseConversationManager {\n const managerRef = useRef<ConversationManager | null>(null);\n const unsubRef = useRef<(() => void) | null>(null);\n const [conversations, setConversations] = useState<AparteConversation[]>([]);\n const [activeId, setActiveId] = useState<string | null>(null);\n\n useEffect(() => () => unsubRef.current?.(), []);\n\n const init = useCallback(async (adapter: AparteStorageAdapter) => {\n const m = new ConversationManager(adapter);\n managerRef.current = m;\n unsubRef.current = m.subscribe((convs) => {\n setConversations([...convs]);\n setActiveId(m.activeId);\n });\n await m.init();\n setActiveId(m.activeId);\n AparteConfig.setConversationManager(m);\n }, []);\n\n const assert = (): ConversationManager => {\n if (!managerRef.current) {\n throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n }\n return managerRef.current;\n };\n\n const activeConversations = useMemo(\n () => conversations.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n [conversations],\n );\n const archivedConversations = useMemo(\n () => conversations.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n [conversations],\n );\n const activeConversation = useMemo(\n () => (activeId ? conversations.find((c) => c.id === activeId) ?? null : null),\n [conversations, activeId],\n );\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n createNew: (title) => assert().createNew(title),\n addMessage: (convId, message) => assert().addMessage(convId, message),\n updateMessages: (convId, messages) => assert().updateMessages(convId, messages),\n delete: (id) => assert().delete(id),\n archive: (id) => assert().archive(id),\n unarchive: (id) => assert().unarchive(id),\n };\n}\n","import { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';\nimport { applyElementProps, DEFAULT_UI_EVENTS } from '@aparte/core';\n\nexport interface AparteUiProps {\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /** Emits a forwarded custom event from the underlying Web Component. */\n onElementEvent?: (event: CustomEvent) => void;\n /**\n * Which custom events to forward through `onElementEvent`. Defaults to the\n * interactive aparté surface ({@link DEFAULT_UI_EVENTS}); pass your own list to\n * listen to other events (e.g. `['aparte-composer-change']` for attachments).\n */\n events?: string[];\n}\n\nexport interface AparteUiHandle {\n getElement: <T extends HTMLElement = HTMLElement>() => T | null;\n callMethod: <T = unknown>(methodName: string, ...args: unknown[]) => T | undefined;\n}\n\n/**\n * Universal pass-through proxy: dynamically mounts any `aparte-*` Web Component so\n * you don't need a dedicated React wrapper per element. React equivalent of\n * Angular's `AparteUiComponent`.\n *\n * @example\n * <AparteUi name=\"aparte-model-selector\" props={{ placeholder: 'Ask…', '--glow-speed': '4s' }} onElementEvent={onEvent} />\n */\nexport const AparteUi = forwardRef<AparteUiHandle, AparteUiProps>(function AparteUi(\n { name, props = {}, onElementEvent, events },\n ref,\n) {\n const hostRef = useRef<HTMLSpanElement>(null);\n const elRef = useRef<HTMLElement | null>(null);\n const cbRef = useRef(onElementEvent);\n cbRef.current = onElementEvent;\n\n const evts = events ?? DEFAULT_UI_EVENTS;\n const evtsKey = evts.join('|');\n\n // (Re)create the element when `name` (or the forwarded event set) changes.\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const el = document.createElement(name);\n elRef.current = el;\n const cleanups: Array<() => void> = [];\n for (const ev of evtsKey.split('|').filter(Boolean)) {\n const listener = (e: Event) => cbRef.current?.(e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el.removeEventListener(ev, listener));\n }\n host.appendChild(el);\n return () => {\n for (const c of cleanups) c();\n el.remove();\n elRef.current = null;\n };\n }, [name, evtsKey]);\n\n // Apply props whenever they change.\n useEffect(() => {\n if (elRef.current) applyElementProps(elRef.current, props);\n }, [props]);\n\n useImperativeHandle(ref, (): AparteUiHandle => ({\n getElement: () => elRef.current as never,\n callMethod: (methodName, ...args) => {\n const fn = (elRef.current as unknown as Record<string, unknown>)?.[methodName];\n return typeof fn === 'function'\n ? (fn as (...a: unknown[]) => unknown).apply(elRef.current, args) as never\n : undefined;\n },\n }), []);\n\n return <span ref={hostRef} style={{ display: 'contents' }} />;\n});\n\nAparteUi.displayName = 'AparteUi';\n"],"names":["AparteChat","composer","AparteUi"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/components/AparteChat.tsx","../src/hooks/useAparteChat.ts","../src/hooks/useAparteClient.ts","../src/hooks/useConversationManager.ts","../src/components/AparteUi.tsx"],"sourcesContent":["'use client';\n\nimport React, {\n useEffect,\n useId,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport { AparteChatHost, isAwaitingReply, type AparteChatHostBinding, type AparteConfig, type AparteChatImperativeApi } from '@aparte/core';\nimport type { AparteMessage, AparteSendEventDetail, AparteActionEventDetail } from '../types.js';\n\nexport interface AparteChatProps {\n /**\n * The host element's `id`, and therefore the `targetId` every event this chat\n * dispatches carries.\n *\n * Generated when omitted, which is the right default — but it used to be\n * generated and neither accepted nor exposed, so\n * `AparteClientOptions.scopeToTargetId` (the documented way to run several\n * independent clients on one page) was unreachable from this component: there\n * was no way to learn the id the client had to match. Angular exposed it; React,\n * Vue and Svelte did not.\n */\n id?: string;\n\n /**\n * Messages on the active path. **Optional** — omit for an uncontrolled chat\n * that starts empty (defaults to `[]`); pass it together with\n * `onMessagesChange` to control the list from the parent.\n */\n messages?: AparteMessage[];\n placeholder?: string;\n disabled?: boolean;\n isTyping?: boolean;\n typingText?: string;\n /** When false, Shift+Enter submits and a bare Enter inserts a newline. */\n submitOnEnter?: boolean;\n /** Freeze viewport spacer recalculation for this many ms after a conv swap. */\n layoutTransitionMs?: number;\n /**\n * Opt in to the \"centered composer when empty\" layout: while the message\n * list is empty the composer sits vertically centered with the `emptyState`\n * content above it, then slides to the bottom on the first message (~0.3s).\n * Off by default — purely additive: adds the `aparte-chat-container--auto-center`\n * modifier + a `data-aparte-empty` attribute that the shipped `aparte.css` recipe\n * keys off. No effect unless you also render an `emptyState`.\n */\n centerWhenEmpty?: boolean;\n /**\n * Add the file picker + chips strip to the default composer shell. **Off by\n * default**, because the capability needs a host that consumes the files: an\n * `AparteClient` inlines them per its `rawFileInject` option, but if you drive\n * your own loop you must read `event.files` in `onMessageSent` — otherwise the\n * file the user deliberately attached is dropped in silence. No effect when you\n * pass your own `composer` (drop `<aparte-composer-add-attachment>` and\n * `<aparte-composer-attachments>` in it yourself).\n */\n attachments?: boolean;\n /**\n * Active conversation id. When set, the wrapper loads/persists via the\n * `AparteConversationManager` registered in `aparteGlobalConfig` (set `null` to deselect).\n */\n conversationId?: string | null;\n /**\n * Custom composer content, rendered inside `<aparte-composer>` in place of the\n * default shell (input · send, plus the attachment primitives when\n * `attachments` is set). Compose the headless\n * `aparte-composer-*` primitives freely — e.g. a skin-specific layout. Omit for\n * the default shell. The `<aparte-composer>` element (and its placeholder /\n * disabled / submit-on-enter behaviour) is always provided by the wrapper.\n */\n composer?: React.ReactNode;\n /**\n * Render your OWN element per message in place of `<aparte-chat-bubble>`.\n * Opt-in — omit for the default bubble. The returned node is driven by the\n * reactive message list, so it updates live during streaming (no need to\n * implement any imperative interface): re-render from `message.content` /\n * `message.segments`. Note the built-in action bar (retry/edit/branch) and\n * the imperative streaming push are the native bubble's — a custom bubble\n * owns whatever it wires (it can dispatch `aparte-retry` etc. or call the\n * wrapper's imperative API).\n */\n renderBubble?: (message: AparteMessage) => React.ReactNode;\n /**\n * Welcome / placeholder content shown INSIDE the viewport while there are no\n * messages (a real \"empty state\" region, not a workaround via `aboveComposer`).\n * Replaced by the message list on the first message.\n */\n emptyState?: React.ReactNode;\n /**\n * Content rendered ABOVE the composer (e.g. a disclaimer banner, a\n * \"scroll to bottom\" affordance, a context chip). Ignored when a full\n * custom `composer` replaces the shell.\n */\n aboveComposer?: React.ReactNode;\n /**\n * The composer's bottom row — a mode picker, a model selector, a token counter.\n * Rendered inside core's `<aparte-composer-toolbar>`; nothing is rendered at all\n * when you pass nothing, so an unused row never draws its separator.\n *\n * **Placement is the DOM order.** There is no left/center/right slot: put things in\n * the order you want them, and push a control (with everything after it) to the end\n * with `margin-inline-start: auto`. That is a logical property, so the row reads\n * correctly in a right-to-left locale with no extra work.\n *\n * Ignored when a full custom `composer` replaces the shell.\n *\n * @example\n * <AparteChat\n * messages={messages}\n * onMessagesChange={setMessages}\n * toolbar={<>\n * <ModePicker value={mode} onChange={setMode} />\n * <ModelSelector style={{ marginInlineStart: 'auto' }} />\n * </>}\n * />\n */\n toolbar?: React.ReactNode;\n\n /**\n * Notification that the user submitted a message from the composer. The\n * user's message is **appended to the thread automatically** (optimistic UI)\n * before this fires — do NOT add it again here. In an uncontrolled chat,\n * appending it duplicates it; in a controlled chat, mirror it into your own\n * `messages`. Use this for side-effects: scroll, analytics, backend send.\n */\n onMessageSent?: (event: AparteSendEventDetail) => void;\n /**\n * Fired when a custom bubble action (registered via\n * `aparteGlobalConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed\n * wrapper over the bubbling `aparte-action` DOM event. Dispatch on `detail.actionId`.\n */\n onAction?: (detail: AparteActionEventDetail) => void;\n /**\n * Fired when the active message path changes (branch navigation / edit /\n * retry / streaming). Set the result back as the `messages` prop.\n */\n onMessagesChange?: (messages: AparteMessage[]) => void;\n /** Fired when a message is appended internally (e.g. by AparteClient). */\n onMessageAppended?: (message: AparteMessage) => void;\n /** Fired when the typing/\"thinking\" indicator should toggle. */\n onTypingChange?: (isTyping: boolean) => void;\n /** Fired when the controller lazily creates a conversation on first send. */\n onConversationCreated?: (id: string) => void;\n\n /**\n * Instance {@link AparteConfig} for this chat. When set, every aparté\n * component rendered inside resolves THIS config instead of the global\n * `aparteGlobalConfig` — letting several independently-configured chats\n * (different providers, tools, renderers) coexist on one page. Omit for the\n * global config. Read once when the host mounts.\n */\n config?: AparteConfig;\n}\n\nexport const AparteChat = forwardRef<AparteChatImperativeApi, AparteChatProps>(function AparteChat(\n {\n messages = [],\n placeholder = 'Type a message...',\n disabled = false,\n isTyping = false,\n typingText = 'Assistant is thinking...',\n submitOnEnter = true,\n layoutTransitionMs = 0,\n centerWhenEmpty = false,\n attachments = false,\n conversationId = null,\n composer,\n renderBubble,\n emptyState,\n aboveComposer,\n toolbar,\n config,\n onMessageSent,\n onAction,\n onMessagesChange,\n onMessageAppended,\n onTypingChange,\n onConversationCreated,\n id: providedId,\n },\n ref,\n) {\n // useId() is SSR-stable (server and client agree), so no hydration mismatch.\n // Strip ':' so the id is also safe in CSS/querySelector, not just getElementById.\n // A caller-supplied id wins, so `scopeToTargetId` has something to match.\n const generatedId = `aparte-chat-${useId().replace(/:/g, '')}`;\n const hostId = providedId ?? generatedId;\n const hostElRef = useRef<HTMLDivElement>(null);\n const viewportRef = useRef<HTMLElement>(null);\n const composerRef = useRef<HTMLElement>(null);\n\n // Authoritative message list lives in a ref (the host reads it synchronously);\n // `renderMessages` state drives the declarative bubble list.\n const messagesRef = useRef<AparteMessage[]>(messages);\n const [renderMessages, setRenderMessages] = useState<AparteMessage[]>(messages);\n const [typingActive, setTypingActive] = useState(isTyping);\n const [, setIsStreaming] = useState(false);\n\n const hostRef = useRef<AparteChatHost | null>(null);\n const lastConvRef = useRef<string | null>(conversationId);\n\n // Keep the latest prop callbacks in a ref so the host's stable binding always\n // calls the current handlers without recreating the host.\n const cbRef = useRef({ onMessageSent, onAction, onMessagesChange, onMessageAppended, onTypingChange, onConversationCreated });\n cbRef.current = { onMessageSent, onAction, onMessagesChange, onMessageAppended, onTypingChange, onConversationCreated };\n\n const applyMessages = (m: AparteMessage[]) => {\n messagesRef.current = m;\n setRenderMessages(m);\n };\n\n // Create the host once after mount.\n useEffect(() => {\n const host = hostElRef.current;\n if (!host) return;\n const binding: AparteChatHostBinding = {\n hostId,\n host,\n viewport: viewportRef.current,\n getMessages: () => messagesRef.current,\n setMessages: (m) => applyMessages(m as AparteMessage[]),\n onMessagesChange: (m) => cbRef.current.onMessagesChange?.(m as AparteMessage[]),\n onMessageAppended: (m) => cbRef.current.onMessageAppended?.(m as AparteMessage),\n onTypingChange: (t) => { setTypingActive(t); cbRef.current.onTypingChange?.(t); },\n onStreamingChange: (id) => setIsStreaming(id !== null),\n afterRender: (cb) => { requestAnimationFrame(() => cb()); },\n resetComposer: () => (composerRef.current as unknown as { reset?: () => void })?.reset?.(),\n };\n const h = new AparteChatHost(binding, {\n layoutTransitionMs,\n conversationId: conversationId ?? null,\n onConversationCreated: (id) => cbRef.current.onConversationCreated?.(id),\n config,\n });\n hostRef.current = h;\n const teardown = h.bind();\n return () => { teardown(); hostRef.current = null; };\n // The host is created once per mount (keyed by the stable hostId); prop\n // changes flow through cbRef / dedicated effects, not by recreating it.\n }, [hostId]);\n\n // Parent push: sync the prop into the authoritative list. Guarded by ref\n // identity so the host's own emit→parent→prop round-trip doesn't loop.\n useEffect(() => {\n if (messages === messagesRef.current) return;\n applyMessages(messages);\n if (messages.length === 0) hostRef.current?.clearRenderCache();\n }, [messages]);\n\n // Reconcile bubbles whenever the rendered list changes (the host queries the\n // DOM for `<aparte-chat-bubble message-id>` elements and pushes segments).\n useEffect(() => { hostRef.current?.syncBubbles(); }, [renderMessages]);\n\n // Controlled typing indicator: reflect the prop, while the host may flip it\n // off internally on the first streamed token.\n useEffect(() => { setTypingActive(isTyping); }, [isTyping]);\n\n // Conversation id changes (the initial value is loaded by the host on bind).\n useEffect(() => {\n if (conversationId === lastConvRef.current) return;\n lastConvRef.current = conversationId;\n void hostRef.current?.setConversationId(conversationId ?? null);\n }, [conversationId]);\n\n // Surface composer sends to the consumer (the controller handles the\n // conversation side separately via its own host listener).\n useEffect(() => {\n const composer = composerRef.current;\n if (!composer) return;\n const onSend = (e: Event) => {\n (viewportRef.current as unknown as { requestSmoothScroll?: () => void })?.requestSmoothScroll?.();\n cbRef.current.onMessageSent?.((e as CustomEvent<AparteSendEventDetail>).detail);\n };\n composer.addEventListener('aparte-send', onSend);\n return () => composer.removeEventListener('aparte-send', onSend);\n }, []);\n\n // aparte-composer exposes `placeholder`/`disabled` as GETTER-ONLY accessors.\n // React 19 sets matching props as PROPERTIES on custom elements, which throws\n // (\"Cannot set property placeholder ... which has only a getter\"). Set them as\n // attributes imperatively instead (the getter reads the attribute).\n useEffect(() => {\n const composer = composerRef.current;\n if (!composer) return;\n composer.setAttribute('placeholder', placeholder);\n if (disabled) composer.setAttribute('disabled', '');\n else composer.removeAttribute('disabled');\n }, [placeholder, disabled]);\n\n // Custom bubble actions bubble to the host root as `aparte-action`; surface them\n // as a typed prop.\n useEffect(() => {\n const host = hostElRef.current;\n if (!host) return;\n const onAct = (e: Event) => cbRef.current.onAction?.((e as CustomEvent<AparteActionEventDetail>).detail);\n host.addEventListener('aparte-action', onAct);\n return () => host.removeEventListener('aparte-action', onAct);\n }, []);\n\n useImperativeHandle(ref, (): AparteChatImperativeApi => ({\n appendMessage: (m) => hostRef.current?.appendMessage(m),\n updateMessage: (id, u) => hostRef.current?.updateMessage(id, u),\n updateLastMessage: (c, o) => hostRef.current?.updateLastMessage(c, o),\n addSegment: (s) => hostRef.current?.addSegment(s),\n updateSegment: (id, u) => hostRef.current?.updateSegment(id, u),\n removeSegment: (id) => hostRef.current?.removeSegment(id),\n appendToSegment: (id, c) => hostRef.current?.appendToSegment(id, c),\n getMessages: () => hostRef.current?.getMessages() ?? messagesRef.current,\n clearMessages: () => hostRef.current?.clearMessages(),\n addBranch: (id) => hostRef.current?.addBranch(id) ?? 0,\n addSiblingOf: (id, m) => hostRef.current?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id) => hostRef.current?.truncateFrom(id),\n truncateResponsesAfter: (id) => hostRef.current?.truncateResponsesAfter(id),\n injectTokenStream: (id, tokens) => hostRef.current?.streamTokens(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => hostRef.current?.stopTokenStream(),\n setConversationId: (id) => hostRef.current?.setConversationId(id) ?? Promise.resolve(),\n scrollToBottom: () => (viewportRef.current as unknown as { scrollToBottom?: () => void })?.scrollToBottom?.(),\n focusInput: () => (composerRef.current as unknown as { focus?: () => void })?.focus?.(),\n isStreaming: () => hostRef.current?.isStreaming ?? false,\n getViewport: () => viewportRef.current,\n }), []);\n\n return (\n <div\n className={`aparte-chat-container${centerWhenEmpty ? ' aparte-chat-container--auto-center' : ''}`}\n data-aparte-chat=\"\"\n data-aparte-empty={centerWhenEmpty && renderMessages.length === 0 ? '' : undefined}\n id={hostId}\n ref={hostElRef}\n >\n <aparte-chat-viewport ref={viewportRef as React.Ref<HTMLElement>} framework-managed=\"\">\n {renderMessages.length === 0 && emptyState}\n {renderMessages.map((m) => (\n renderBubble\n ? <React.Fragment key={m.id}>{renderBubble(m)}</React.Fragment>\n : (\n <aparte-chat-bubble\n key={m.id}\n message-id={m.id}\n data-role={m.role}\n timestamp={m.timestamp}\n content={m.content}\n streaming={isAwaitingReply(m) ? '' : undefined}\n />\n )\n ))}\n <aparte-chat-status visible={typingActive ? '' : undefined} text={typingText} />\n </aparte-chat-viewport>\n\n {aboveComposer}\n\n <aparte-composer\n ref={composerRef as React.Ref<HTMLElement>}\n target={hostId}\n submit-on-enter={submitOnEnter ? undefined : 'false'}\n >\n {composer ?? (\n <div className=\"aparte-composer-shell\">\n {attachments && <aparte-composer-attachments />}\n <div className=\"aparte-composer-row\">\n {attachments && <aparte-composer-add-attachment />}\n <aparte-composer-input />\n <aparte-composer-send />\n </div>\n {toolbar != null && (\n <aparte-composer-toolbar>{toolbar}</aparte-composer-toolbar>\n )}\n </div>\n )}\n </aparte-composer>\n </div>\n );\n});\n\nAparteChat.displayName = 'AparteChat';\n","import { useRef, useState } from 'react';\nimport type { AparteMessage, AparteSegment } from '../types.js';\nimport type { AparteChatImperativeApi } from '@aparte/core';\n\n/**\n * Idiomatic React ergonomics for `<AparteChat>`. Owns the `messages` state and\n * the component ref so the consumer doesn't have to wire `onMessagesChange`\n * back into `messages` by hand. Spread `ref` + `messages` + `onMessagesChange`\n * onto `<AparteChat>` and drive it with the returned imperative helpers.\n *\n * @example\n * const chat = useAparteChat();\n * return (\n * <AparteChat\n * ref={chat.ref}\n * messages={chat.messages}\n * onMessagesChange={chat.setMessages}\n * />\n * );\n * // The user's message is appended automatically on send — don't re-add it.\n */\nexport interface UseAparteChat {\n messages: AparteMessage[];\n setMessages: React.Dispatch<React.SetStateAction<AparteMessage[]>>;\n // Typed to match `<AparteChat>`'s forwardRef target so `ref={chat.ref}`\n // typechecks verbatim — @types/react 18.3's variance rejects the\n // useRef(null) `RefObject<T | null>` shape against `Ref<T>`, so the (safe)\n // cast lives here once, not in every consumer.\n ref: React.RefObject<AparteChatImperativeApi>;\n // ── imperative helpers (delegate to the component handle) ──\n appendMessage: (message: AparteMessage) => void;\n updateMessage: (messageId: string, updates: Partial<AparteMessage>) => void;\n updateLastMessage: (content: string, options?: { append?: boolean }) => void;\n addSegment: (segment: AparteSegment) => void;\n updateSegment: (segmentId: string, updates: Partial<AparteSegment>) => void;\n removeSegment: (segmentId: string) => void;\n appendToSegment: (segmentId: string, content: string) => void;\n clearMessages: () => void;\n addBranch: (messageId: string) => number;\n addSiblingOf: (existingId: string, message: AparteMessage) => string | null;\n truncateFrom: (messageId: string) => void;\n truncateResponsesAfter: (userMessageId: string) => void;\n injectTokenStream: (messageId: string, tokens: AsyncIterable<string>) => Promise<void>;\n stopTokenStream: () => void;\n setConversationId: (id: string | null) => Promise<void>;\n isStreaming: () => boolean;\n}\n\nexport function useAparteChat(initial: AparteMessage[] = []): UseAparteChat {\n const [messages, setMessages] = useState<AparteMessage[]>(initial);\n const ref = useRef<AparteChatImperativeApi | null>(null);\n const h = () => ref.current;\n return {\n messages,\n setMessages,\n ref: ref as React.RefObject<AparteChatImperativeApi>,\n appendMessage: (m) => h()?.appendMessage(m),\n updateMessage: (id, u) => h()?.updateMessage(id, u),\n updateLastMessage: (c, o) => h()?.updateLastMessage(c, o),\n addSegment: (s) => h()?.addSegment(s),\n updateSegment: (id, u) => h()?.updateSegment(id, u),\n removeSegment: (id) => h()?.removeSegment(id),\n appendToSegment: (id, c) => h()?.appendToSegment(id, c),\n clearMessages: () => h()?.clearMessages(),\n addBranch: (id) => h()?.addBranch(id) ?? 0,\n addSiblingOf: (id, m) => h()?.addSiblingOf(id, m) ?? null,\n truncateFrom: (id) => h()?.truncateFrom(id),\n truncateResponsesAfter: (id) => h()?.truncateResponsesAfter(id),\n injectTokenStream: (id, tokens) => h()?.injectTokenStream(id, tokens) ?? Promise.resolve(),\n stopTokenStream: () => h()?.stopTokenStream(),\n setConversationId: (id) => h()?.setConversationId(id) ?? Promise.resolve(),\n isStreaming: () => h()?.isStreaming() ?? false,\n };\n}\n","import { useEffect, useRef } from 'react';\nimport { AparteClient, type AparteClientOptions } from '@aparte/core';\n\nexport interface UseAparteClient {\n /** The underlying agnostic client. */\n client: AparteClient;\n /** Abort the current AI response + all active tool calls. */\n abort: () => void;\n}\n\n/**\n * Mounts an `AparteClient` that bridges `aparte-send` events to the configured AI\n * providers. Starts listening on mount, stops on unmount. React equivalent of\n * Angular's `AparteAiService`.\n *\n * @example\n * const { abort } = useAparteClient({ keyResolver });\n */\nexport function useAparteClient(options?: AparteClientOptions): UseAparteClient {\n const ref = useRef<AparteClient | null>(null);\n if (!ref.current) ref.current = new AparteClient(options ?? {});\n useEffect(() => {\n const c = ref.current as AparteClient;\n c.start();\n return () => c.stop();\n }, []);\n return { client: ref.current, abort: () => ref.current?.abort() };\n}\n","import { useEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport {\n aparteGlobalConfig,\n type AparteConfig,\n AparteConversationManager,\n type AparteConversation,\n type AparteStorageAdapter,\n} from '@aparte/core';\nimport type { AparteMessage } from '../types.js';\n\nexport interface UseConversationManager {\n conversations: AparteConversation[];\n /** Active conversations, newest first. */\n activeConversations: AparteConversation[];\n /** Archived conversations, newest first. */\n archivedConversations: AparteConversation[];\n activeId: string | null;\n activeConversation: AparteConversation | null;\n /** Initialise with a storage adapter (call once). */\n init: (adapter: AparteStorageAdapter) => Promise<void>;\n createNew: (title?: string) => Promise<AparteConversation>;\n addMessage: (convId: string, message: AparteMessage) => Promise<void>;\n updateMessages: (convId: string, messages: AparteMessage[]) => Promise<void>;\n delete: (id: string) => Promise<void>;\n archive: (id: string) => Promise<void>;\n unarchive: (id: string) => Promise<void>;\n}\n\n/**\n * React-state wrapper around the core `AparteConversationManager`. The active\n * conversation is owned by the chat component's controller; switch by binding\n * `conversationId` on `<AparteChat>`. React equivalent of Angular's\n * `ConversationManagerService`.\n */\nexport function useConversationManager(): UseConversationManager {\n const managerRef = useRef<AparteConversationManager | null>(null);\n const unsubRef = useRef<(() => void) | null>(null);\n const [conversations, setConversations] = useState<AparteConversation[]>([]);\n const [activeId, setActiveId] = useState<string | null>(null);\n\n useEffect(() => () => unsubRef.current?.(), []);\n\n /**\n * Initialise with a storage adapter.\n *\n * `config` defaults to the global singleton. Pass the SAME config you gave\n * `<AparteChat config={…}>`: the controller resolves the config governing its\n * host element, so a manager registered on the global is invisible to a chat\n * with its own — persistence silently does nothing while the optimistic UI\n * keeps working.\n */\n const init = useCallback(async (adapter: AparteStorageAdapter, config: AparteConfig = aparteGlobalConfig) => {\n const m = new AparteConversationManager(adapter);\n managerRef.current = m;\n unsubRef.current = m.subscribe((convs) => {\n setConversations([...convs]);\n setActiveId(m.activeId);\n });\n await m.init();\n setActiveId(m.activeId);\n config.setConversationManager(m);\n }, []);\n\n const assert = (): AparteConversationManager => {\n if (!managerRef.current) {\n throw new Error('[useConversationManager] Not initialised. Call init(adapter) first.');\n }\n return managerRef.current;\n };\n\n const activeConversations = useMemo(\n () => conversations.filter((c) => !c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n [conversations],\n );\n const archivedConversations = useMemo(\n () => conversations.filter((c) => !!c.archivedAt).sort((a, b) => b.updatedAt - a.updatedAt),\n [conversations],\n );\n const activeConversation = useMemo(\n () => (activeId ? conversations.find((c) => c.id === activeId) ?? null : null),\n [conversations, activeId],\n );\n\n return {\n conversations,\n activeConversations,\n archivedConversations,\n activeId,\n activeConversation,\n init,\n createNew: (title) => assert().createNew(title),\n addMessage: (convId, message) => assert().addMessage(convId, message),\n updateMessages: (convId, messages) => assert().updateMessages(convId, messages),\n delete: (id) => assert().delete(id),\n archive: (id) => assert().archive(id),\n unarchive: (id) => assert().unarchive(id),\n };\n}\n","import { useEffect, useRef, forwardRef, useImperativeHandle } from 'react';\nimport { applyElementProps, APARTE_DEFAULT_UI_EVENTS } from '@aparte/core';\n\nexport interface AparteUiProps {\n /** The custom element tag name (e.g. 'aparte-model-selector'). */\n name: string;\n /** Props to apply. Keys starting with `--` become CSS variables. */\n props?: Record<string, unknown>;\n /** Emits a forwarded custom event from the underlying Web Component. */\n onElementEvent?: (event: CustomEvent) => void;\n /**\n * Which custom events to forward through `onElementEvent`. Defaults to the\n * interactive aparté surface ({@link APARTE_DEFAULT_UI_EVENTS}); pass your own list to\n * listen to other events (e.g. `['aparte-composer-change']` for attachments).\n */\n events?: string[];\n}\n\nexport interface AparteUiHandle {\n getElement: <T extends HTMLElement = HTMLElement>() => T | null;\n callMethod: <T = unknown>(methodName: string, ...args: unknown[]) => T | undefined;\n}\n\n/**\n * Universal pass-through proxy: dynamically mounts any `aparte-*` Web Component so\n * you don't need a dedicated React wrapper per element. React equivalent of\n * Angular's `AparteUiComponent`.\n *\n * `name` can be any custom element, including one of yours. `aparte-model-selector`\n * below is defined by `@aparte/plugin-model-selector`, not by core — until that\n * package is imported the tag mounts empty and inert with no error, and upgrades on\n * its own once the definition arrives (which is what makes lazy-loading it work).\n *\n * @example\n * <AparteUi name=\"aparte-model-selector\" props={{ placeholder: 'Ask…', '--glow-speed': '4s' }} onElementEvent={onEvent} />\n */\nexport const AparteUi = forwardRef<AparteUiHandle, AparteUiProps>(function AparteUi(\n { name, props = {}, onElementEvent, events },\n ref,\n) {\n const hostRef = useRef<HTMLSpanElement>(null);\n const elRef = useRef<HTMLElement | null>(null);\n const cbRef = useRef(onElementEvent);\n cbRef.current = onElementEvent;\n\n const evts = events ?? APARTE_DEFAULT_UI_EVENTS;\n const evtsKey = evts.join('|');\n\n // (Re)create the element when `name` (or the forwarded event set) changes.\n useEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n const el = document.createElement(name);\n elRef.current = el;\n const cleanups: Array<() => void> = [];\n for (const ev of evtsKey.split('|').filter(Boolean)) {\n const listener = (e: Event) => cbRef.current?.(e as CustomEvent);\n el.addEventListener(ev, listener);\n cleanups.push(() => el.removeEventListener(ev, listener));\n }\n host.appendChild(el);\n return () => {\n for (const c of cleanups) c();\n el.remove();\n elRef.current = null;\n };\n }, [name, evtsKey]);\n\n // Apply props whenever they change.\n useEffect(() => {\n if (elRef.current) applyElementProps(elRef.current, props);\n }, [props]);\n\n useImperativeHandle(ref, (): AparteUiHandle => ({\n getElement: () => elRef.current as never,\n callMethod: (methodName, ...args) => {\n const fn = (elRef.current as unknown as Record<string, unknown>)?.[methodName];\n return typeof fn === 'function'\n ? (fn as (...a: unknown[]) => unknown).apply(elRef.current, args) as never\n : undefined;\n },\n }), []);\n\n return <span ref={hostRef} style={{ display: 'contents' }} />;\n});\n\nAparteUi.displayName = 'AparteUi';\n"],"names":["AparteChat","composer","AparteUi"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/react",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "React 18+ wrapper for aparté — an ergonomic <AparteChat> component plus hooks over the framework-agnostic web components.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -24,7 +24,7 @@
24
24
  "node": ">=18"
25
25
  },
26
26
  "peerDependencies": {
27
- "@aparte/core": ">=0.5.0-alpha.0 <1.0.0",
27
+ "@aparte/core": ">=0.7.0 <1.0.0",
28
28
  "react": "^18.0.0 || ^19.0.0",
29
29
  "react-dom": "^18.0.0 || ^19.0.0"
30
30
  },
@@ -39,7 +39,7 @@
39
39
  "react-dom": "^19.2.7",
40
40
  "typescript": "^5.4.0",
41
41
  "vite": "^6.0.0",
42
- "@aparte/core": "0.7.0"
42
+ "@aparte/core": "0.8.0"
43
43
  },
44
44
  "keywords": [
45
45
  "react",