@anvia/react-ui 1.0.0-rc.9 → 1.0.1

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.
Files changed (60) hide show
  1. package/README.md +44 -37
  2. package/dist/attachment/index.d.ts +2 -2
  3. package/dist/attachment/index.js +4 -4
  4. package/dist/chat/index.d.ts +4 -4
  5. package/dist/chat/index.js +10 -9
  6. package/dist/{chunk-OINUOCTO.js → chunk-647LAYRV.js} +90 -65
  7. package/dist/chunk-647LAYRV.js.map +1 -0
  8. package/dist/chunk-6XOJFLX4.js +22 -0
  9. package/dist/chunk-6XOJFLX4.js.map +1 -0
  10. package/dist/{chunk-JBKSJG5W.js → chunk-CRXNFZRW.js} +45 -80
  11. package/dist/chunk-CRXNFZRW.js.map +1 -0
  12. package/dist/{chunk-ULGJLLZE.js → chunk-F6AKBUO3.js} +12 -12
  13. package/dist/chunk-F6AKBUO3.js.map +1 -0
  14. package/dist/{chunk-XAQA3JIG.js → chunk-HWJIMLHC.js} +41 -70
  15. package/dist/chunk-HWJIMLHC.js.map +1 -0
  16. package/dist/{chunk-BU4ZPDHQ.js → chunk-MISX4WUT.js} +10 -15
  17. package/dist/chunk-MISX4WUT.js.map +1 -0
  18. package/dist/{chunk-PSU4V23X.js → chunk-OQE6SHZE.js} +16 -30
  19. package/dist/chunk-OQE6SHZE.js.map +1 -0
  20. package/dist/{chunk-E5UNQCGM.js → chunk-S4XLE2RN.js} +6 -12
  21. package/dist/chunk-S4XLE2RN.js.map +1 -0
  22. package/dist/{chunk-F76H3VMN.js → chunk-SOG2GVE4.js} +45 -15
  23. package/dist/chunk-SOG2GVE4.js.map +1 -0
  24. package/dist/{chunk-ZPNAX4SA.js → chunk-UCBAG42A.js} +9 -21
  25. package/dist/chunk-UCBAG42A.js.map +1 -0
  26. package/dist/{chunk-EWIHRMU6.js → chunk-XC7K4XYM.js} +21 -28
  27. package/dist/chunk-XC7K4XYM.js.map +1 -0
  28. package/dist/completion/index.d.ts +2 -2
  29. package/dist/completion/index.js +4 -4
  30. package/dist/human-input/index.d.ts +2 -2
  31. package/dist/human-input/index.js +4 -4
  32. package/dist/image/index.d.ts +2 -2
  33. package/dist/image/index.js +4 -4
  34. package/dist/index.d.ts +11 -11
  35. package/dist/index.js +58 -63
  36. package/dist/index.js.map +1 -1
  37. package/dist/message/index.d.ts +2 -2
  38. package/dist/message/index.js +7 -6
  39. package/dist/selection-toolbar/index.d.ts +2 -2
  40. package/dist/selection-toolbar/index.js +5 -4
  41. package/dist/shared.d.ts +1 -1
  42. package/dist/shared.js +1 -1
  43. package/dist/stream/index.d.ts +2 -0
  44. package/dist/stream/index.js +1 -1
  45. package/dist/{thread-uEm8hH0s.d.ts → thread-Bz6-1zaJ.d.ts} +1 -0
  46. package/dist/thread-list/index.d.ts +3 -3
  47. package/dist/thread-list/index.js +6 -6
  48. package/package.json +18 -20
  49. package/dist/chunk-BU4ZPDHQ.js.map +0 -1
  50. package/dist/chunk-E5UNQCGM.js.map +0 -1
  51. package/dist/chunk-EWIHRMU6.js.map +0 -1
  52. package/dist/chunk-F76H3VMN.js.map +0 -1
  53. package/dist/chunk-JBKSJG5W.js.map +0 -1
  54. package/dist/chunk-OINUOCTO.js.map +0 -1
  55. package/dist/chunk-PSU4V23X.js.map +0 -1
  56. package/dist/chunk-ULGJLLZE.js.map +0 -1
  57. package/dist/chunk-XAQA3JIG.js.map +0 -1
  58. package/dist/chunk-ZPNAX4SA.js.map +0 -1
  59. package/dist/stream/styles.css +0 -17
  60. package/dist/styles.css +0 -130
package/README.md CHANGED
@@ -5,7 +5,12 @@ Composable React UI primitives for Anvia chat and completion experiences.
5
5
  ```tsx
6
6
  import { createHttpClientTransport } from "@anvia/client";
7
7
  import { useChat } from "@anvia/react";
8
- import { ChatProvider, Composer, Message, Thread } from "@anvia/react-ui";
8
+ import {
9
+ ChatProvider,
10
+ ComposerPrimitive,
11
+ MessagePrimitive,
12
+ ThreadPrimitive,
13
+ } from "@anvia/react-ui";
9
14
 
10
15
  export function SupportChat() {
11
16
  const chat = useChat({
@@ -21,55 +26,56 @@ export function SupportChat() {
21
26
 
22
27
  return (
23
28
  <ChatProvider controller={chat}>
24
- <Thread.Root>
25
- <Thread.Viewport>
26
- <Thread.Empty>Start a conversation.</Thread.Empty>
27
- <Thread.Suggestions />
28
- <Thread.Messages>
29
- <Message.Root>
30
- <Message.Content>
31
- <Message.Parts />
32
- </Message.Content>
33
- <Message.Actions />
34
- </Message.Root>
35
- </Thread.Messages>
36
- <Thread.Error />
37
- <Thread.ScrollToBottom>Jump to latest</Thread.ScrollToBottom>
38
- </Thread.Viewport>
39
- <Composer.Root triggers={triggers}>
40
- <Composer.Attachments />
41
- <Composer.AddAttachment>Attach</Composer.AddAttachment>
42
- <Composer.Input maxRows={6} placeholder="Send a message..." />
43
- <Composer.TriggerMenu />
44
- <Composer.Stop>Stop</Composer.Stop>
45
- <Composer.Submit>Send</Composer.Submit>
46
- </Composer.Root>
47
- </Thread.Root>
29
+ <ThreadPrimitive.Root>
30
+ <ThreadPrimitive.Viewport>
31
+ <ThreadPrimitive.Empty>Start a conversation.</ThreadPrimitive.Empty>
32
+ <ThreadPrimitive.Suggestions />
33
+ <ThreadPrimitive.Messages>
34
+ <MessagePrimitive.Root>
35
+ <MessagePrimitive.Content>
36
+ <MessagePrimitive.Parts />
37
+ </MessagePrimitive.Content>
38
+ <MessagePrimitive.Actions />
39
+ </MessagePrimitive.Root>
40
+ </ThreadPrimitive.Messages>
41
+ <ThreadPrimitive.Error />
42
+ <ThreadPrimitive.ScrollToBottom>Jump to latest</ThreadPrimitive.ScrollToBottom>
43
+ </ThreadPrimitive.Viewport>
44
+ <ComposerPrimitive.Root triggers={triggers}>
45
+ <ComposerPrimitive.Attachments />
46
+ <ComposerPrimitive.AddAttachment>Attach</ComposerPrimitive.AddAttachment>
47
+ <ComposerPrimitive.Input maxRows={6} placeholder="Send a message..." />
48
+ <ComposerPrimitive.TriggerMenu />
49
+ <ComposerPrimitive.Stop>Stop</ComposerPrimitive.Stop>
50
+ <ComposerPrimitive.Submit>Send</ComposerPrimitive.Submit>
51
+ </ComposerPrimitive.Root>
52
+ </ThreadPrimitive.Root>
48
53
  </ChatProvider>
49
54
  );
50
55
  }
51
56
  ```
52
57
 
53
- Import `@anvia/react-ui/styles.css` for a small default stylesheet, or style the stable
54
- `data-anvia-*` attributes directly.
58
+ The primitives are headless: pass `className` or `asChild` for design-system integration. Their
59
+ small semantic DOM contract consists of ARIA attributes, `data-state`, and `data-role`; there is no
60
+ package stylesheet. For editable, styled application components, run
61
+ `pnpm dlx @anvia/cli add chat`.
55
62
 
56
- The primitives are headless by default: pass `className` or `asChild` for design-system
57
- integration, control `Composer.Root` with `input`/`attachments` props when needed, and use
63
+ Control `ComposerPrimitive.Root` with `input`/`attachments` props when needed, and use
58
64
  `submitMessage` for custom composer payloads. Use `keepMounted` on optional collections when empty
59
65
  wrappers are useful for layout.
60
66
 
61
- `Composer.Input` is a Tiptap-backed rich composer. Configure `Composer.Root` with `triggers` to
67
+ `ComposerPrimitive.Input` is a Tiptap-backed rich composer. Configure `ComposerPrimitive.Root` with `triggers` to
62
68
  support inline `@`, `/`, `$`, or other entity chips; selected entities are submitted under
63
69
  `metadata.composer.entities`. Entity `data` must be finite strict JSON; class instances, sparse or
64
70
  custom-prototype arrays, accessors, symbols, cycles, `undefined`, and non-finite numbers are
65
- rejected. Use `Composer.TextareaInput` when you need the previous native textarea behavior.
71
+ rejected. Use `ComposerPrimitive.TextareaInput` when you need the previous native textarea behavior.
66
72
 
67
73
  Streaming smoothing is opt-in and display-only. Keep `useChat` as the owner of transport and
68
74
  `UIMessage[]` state. Keep the lifecycle mounted after streaming stops so its buffered tail drains;
69
- `Message.Parts` also keeps later tool parts behind text that has not been revealed yet:
75
+ `MessagePrimitive.Parts` also keeps later tool parts behind text that has not been revealed yet:
70
76
 
71
77
  ```tsx
72
- <Message.Parts
78
+ <MessagePrimitive.Parts
73
79
  stream={{
74
80
  isStreaming:
75
81
  chat.status === "streaming" &&
@@ -79,10 +85,11 @@ Streaming smoothing is opt-in and display-only. Keep `useChat` as the owner of t
79
85
  flushImmediately: chat.status === "error",
80
86
  }}
81
87
  >
82
- {(part) => (part.type === "text" ? <Message.Markdown /> : <Message.Part />)}
83
- </Message.Parts>
88
+ {(part) => (part.type === "text" ? <MessagePrimitive.Markdown /> : <MessagePrimitive.Part />)}
89
+ </MessagePrimitive.Parts>
84
90
  ```
85
91
 
86
92
  For app-owned text state, `StreamMarkdown` is available from `@anvia/react-ui/stream`. It is a
87
- context-free renderer: pass the already displayed text as `content`, set `live` only for its growing
88
- tail, and import `@anvia/react-ui/stream/styles.css` for the settle animation.
93
+ context-free renderer: pass the already displayed text as `content` and set `live` only for its
94
+ growing tail. Style `[data-state="revealing"]` in the owning application; `@anvia/cli` installs this
95
+ animation with its `markdown`, `message`, `thread`, and `chat` items.
@@ -3,7 +3,7 @@ import * as react from 'react';
3
3
  export { A as AttachmentContextValue, u as useAttachment } from '../attachment-mbjsroli.js';
4
4
  import { P as PrimitiveProps } from '../render-CRKWam2v.js';
5
5
 
6
- declare const Attachment: {
6
+ declare const AttachmentPrimitive: {
7
7
  readonly Root: react.ForwardRefExoticComponent<Omit<PrimitiveProps<"div">, "children"> & {
8
8
  children?: react.ReactNode | ((attachment: _anvia_client.UIAttachment) => react.ReactNode);
9
9
  } & react.RefAttributes<HTMLDivElement>>;
@@ -18,4 +18,4 @@ declare const Attachment: {
18
18
  } & react.RefAttributes<HTMLButtonElement>>;
19
19
  };
20
20
 
21
- export { Attachment };
21
+ export { AttachmentPrimitive };
@@ -1,12 +1,12 @@
1
1
  import {
2
- Attachment
3
- } from "../chunk-BU4ZPDHQ.js";
2
+ AttachmentPrimitive
3
+ } from "../chunk-MISX4WUT.js";
4
4
  import "../chunk-T3ZFZ3NP.js";
5
5
  import {
6
6
  useAttachment
7
- } from "../chunk-F76H3VMN.js";
7
+ } from "../chunk-SOG2GVE4.js";
8
8
  export {
9
- Attachment,
9
+ AttachmentPrimitive,
10
10
  useAttachment
11
11
  };
12
12
  //# sourceMappingURL=index.js.map
@@ -2,7 +2,7 @@ import { C as ChatController } from '../chat-tfA570mg.js';
2
2
  export { a as ChatProvider, b as ChatProviderProps, u as useChatContext } from '../chat-tfA570mg.js';
3
3
  import { d as ComposerEntity, g as ComposerQuote, h as ComposerTriggerDefinition, l as ComposerTriggerState, i as ComposerTriggerItem } from '../composer-CigccTLT.js';
4
4
  export { C as ComposerAttachmentInput, a as ComposerAttachmentsUpdate, b as ComposerContextValue, c as ComposerEntitiesUpdate, e as ComposerEntityData, f as ComposerMessageMetadata, j as ComposerTriggerItems, k as ComposerTriggerItemsArgs, m as ComposerTriggerStateUpdate, u as useComposer } from '../composer-CigccTLT.js';
5
- export { T as ThreadContextValue, u as useThread } from '../thread-uEm8hH0s.js';
5
+ export { T as ThreadContextValue, u as useThread } from '../thread-Bz6-1zaJ.js';
6
6
  import * as react from 'react';
7
7
  import { ReactNode } from 'react';
8
8
  import { UIAttachment, ClientDataMap, ClientMetadata, UIMessage } from '@anvia/client';
@@ -21,7 +21,7 @@ type ComposerSubmitMessage<TData extends ClientDataMap = ClientDataMap> = (args:
21
21
  type ComposerTriggerMenuChildren = ReactNode | ((trigger: ComposerTriggerState) => ReactNode);
22
22
  type ComposerTriggerItemChildren = ReactNode | ((item: ComposerTriggerItem, trigger: ComposerTriggerState) => ReactNode);
23
23
  type ComposerAttachmentsChildren = ReactNode | ((attachment: UIAttachment) => ReactNode);
24
- declare const Composer: {
24
+ declare const ComposerPrimitive: {
25
25
  readonly Root: react.ForwardRefExoticComponent<Omit<Omit<react.DetailedHTMLProps<react.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "ref">, "asChild"> & {
26
26
  asChild?: boolean;
27
27
  } & {
@@ -99,7 +99,7 @@ declare const Composer: {
99
99
 
100
100
  type ThreadMessagesChildren = ReactNode | ((message: UIMessage) => ReactNode);
101
101
  type ThreadSuggestionChildren = ReactNode | ((suggestion: ChatSuggestion) => ReactNode);
102
- declare const Thread: {
102
+ declare const ThreadPrimitive: {
103
103
  readonly Root: react.ForwardRefExoticComponent<Omit<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "asChild"> & {
104
104
  asChild?: boolean;
105
105
  } & react.RefAttributes<HTMLDivElement>>;
@@ -141,4 +141,4 @@ declare const Thread: {
141
141
  } & react.RefAttributes<HTMLButtonElement>>;
142
142
  };
143
143
 
144
- export { ChatController, Composer, ComposerEntity, ComposerQuote, type ComposerSubmitMessage, type ComposerSubmitMessageArgs, ComposerTriggerDefinition, ComposerTriggerItem, ComposerTriggerState, Thread };
144
+ export { ChatController, ComposerEntity, ComposerPrimitive, ComposerQuote, type ComposerSubmitMessage, type ComposerSubmitMessageArgs, ComposerTriggerDefinition, ComposerTriggerItem, ComposerTriggerState, ThreadPrimitive };
@@ -1,10 +1,11 @@
1
1
  import {
2
- Composer,
3
- Thread
4
- } from "../chunk-XAQA3JIG.js";
5
- import "../chunk-JBKSJG5W.js";
6
- import "../chunk-ULGJLLZE.js";
7
- import "../chunk-BU4ZPDHQ.js";
2
+ ComposerPrimitive,
3
+ ThreadPrimitive
4
+ } from "../chunk-HWJIMLHC.js";
5
+ import "../chunk-CRXNFZRW.js";
6
+ import "../chunk-6XOJFLX4.js";
7
+ import "../chunk-F6AKBUO3.js";
8
+ import "../chunk-MISX4WUT.js";
8
9
  import "../chunk-CKA4CE26.js";
9
10
  import "../chunk-T3ZFZ3NP.js";
10
11
  import {
@@ -12,11 +13,11 @@ import {
12
13
  useChatContext,
13
14
  useComposer,
14
15
  useThread
15
- } from "../chunk-F76H3VMN.js";
16
+ } from "../chunk-SOG2GVE4.js";
16
17
  export {
17
18
  ChatProvider,
18
- Composer,
19
- Thread,
19
+ ComposerPrimitive,
20
+ ThreadPrimitive,
20
21
  useChatContext,
21
22
  useComposer,
22
23
  useThread
@@ -1,31 +1,61 @@
1
1
  import {
2
+ composeRefs,
2
3
  renderPrimitive
3
4
  } from "./chunk-T3ZFZ3NP.js";
4
5
  import {
5
6
  InternalThreadListItemProvider,
7
+ InternalThreadListRootProvider,
8
+ useInternalThreadListRoot,
6
9
  useThreadList,
7
10
  useThreadListItem
8
- } from "./chunk-F76H3VMN.js";
11
+ } from "./chunk-SOG2GVE4.js";
9
12
 
10
13
  // src/thread-list/parts.tsx
11
14
  import {
12
15
  forwardRef,
13
- useCallback
16
+ useCallback,
17
+ useMemo,
18
+ useRef
14
19
  } from "react";
15
20
  import { jsx } from "react/jsx-runtime";
16
21
  var ThreadListRoot = forwardRef(function ThreadListRoot2({ onKeyDown, ...props }, ref) {
17
22
  const threadList = useThreadList();
23
+ const rootRef = useRef(null);
24
+ const newButtonRef = useRef(null);
25
+ const itemElements = useRef(/* @__PURE__ */ new Map());
26
+ const triggerElements = useRef(/* @__PURE__ */ new Map());
27
+ const registerItem = useCallback((threadId, element) => {
28
+ if (element === null) itemElements.current.delete(threadId);
29
+ else itemElements.current.set(threadId, element);
30
+ }, []);
31
+ const registerTrigger = useCallback((threadId, element) => {
32
+ if (element === null) triggerElements.current.delete(threadId);
33
+ else triggerElements.current.set(threadId, element);
34
+ }, []);
35
+ const rootContext = useMemo(
36
+ () => ({
37
+ rootRef,
38
+ newButtonRef,
39
+ itemElements,
40
+ triggerElements,
41
+ registerItem,
42
+ registerTrigger
43
+ }),
44
+ [registerItem, registerTrigger]
45
+ );
46
+ const composedRef = useMemo(
47
+ () => composeRefs(ref, (node) => {
48
+ rootRef.current = node;
49
+ }),
50
+ [ref]
51
+ );
18
52
  const handleKeyDown = useCallback(
19
53
  (event) => {
20
54
  onKeyDown?.(event);
21
55
  if (event.defaultPrevented || !["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) {
22
56
  return;
23
57
  }
24
- const triggers = Array.from(
25
- event.currentTarget.querySelectorAll(
26
- "[data-anvia-thread-list-trigger]:not(:disabled)"
27
- )
28
- );
58
+ const triggers = orderedEnabledTriggers(rootContext);
29
59
  if (triggers.length === 0) {
30
60
  return;
31
61
  }
@@ -35,22 +65,28 @@ var ThreadListRoot = forwardRef(function ThreadListRoot2({ onKeyDown, ...props }
35
65
  const nextIndex = nextTriggerIndex(event.key, currentIndex, triggers.length);
36
66
  triggers[nextIndex]?.focus();
37
67
  },
38
- [onKeyDown]
68
+ [onKeyDown, rootContext]
39
69
  );
40
- return renderPrimitive(
70
+ return /* @__PURE__ */ jsx(InternalThreadListRootProvider, { value: rootContext, children: renderPrimitive(
41
71
  "div",
42
72
  {
43
73
  ...props,
44
74
  onKeyDown: handleKeyDown,
45
- "data-anvia-thread-list": "",
46
75
  "data-state": threadList.status ?? "idle"
47
76
  },
48
- ref
49
- );
77
+ composedRef
78
+ ) });
50
79
  });
51
80
  var ThreadListNew = forwardRef(
52
81
  function ThreadListNew2({ onClick, ...props }, ref) {
53
82
  const threadList = useThreadList();
83
+ const root = useInternalThreadListRoot();
84
+ const composedRef = useMemo(
85
+ () => composeRefs(ref, (node) => {
86
+ root.newButtonRef.current = node;
87
+ }),
88
+ [ref, root.newButtonRef]
89
+ );
54
90
  const handleClick = useCallback(
55
91
  (event) => {
56
92
  onClick?.(event);
@@ -68,10 +104,9 @@ var ThreadListNew = forwardRef(
68
104
  children: props.children ?? "New chat",
69
105
  onClick: handleClick,
70
106
  type: props.type ?? "button",
71
- "data-anvia-thread-list-new": "",
72
107
  "data-state": props.disabled ? "disabled" : "enabled"
73
108
  },
74
- ref
109
+ composedRef
75
110
  );
76
111
  }
77
112
  );
@@ -94,9 +129,7 @@ var ThreadListItems = forwardRef(function ThreadListItems2({ archived = false, c
94
129
  },
95
130
  thread.id
96
131
  )),
97
- "data-anvia-thread-list-items": "",
98
- "data-archived": archived ? "" : void 0,
99
- "data-empty": empty ? "" : void 0
132
+ "data-state": empty ? "empty" : "populated"
100
133
  },
101
134
  ref
102
135
  );
@@ -113,8 +146,7 @@ var ThreadListEmpty = forwardRef(function ThreadListEmpty2({ archived = false, .
113
146
  "div",
114
147
  {
115
148
  ...props,
116
- children: props.children ?? "No conversations.",
117
- "data-anvia-thread-list-empty": ""
149
+ children: props.children ?? "No conversations."
118
150
  },
119
151
  ref
120
152
  );
@@ -122,15 +154,18 @@ var ThreadListEmpty = forwardRef(function ThreadListEmpty2({ archived = false, .
122
154
  var ThreadListItemRoot = forwardRef(
123
155
  function ThreadListItemRoot2(props, ref) {
124
156
  const item = useThreadListItem();
157
+ const root = useInternalThreadListRoot();
158
+ const composedRef = useMemo(
159
+ () => composeRefs(ref, (node) => root.registerItem(item.thread.id, node)),
160
+ [item.thread.id, ref, root]
161
+ );
125
162
  return renderPrimitive(
126
163
  "div",
127
164
  {
128
165
  ...props,
129
- "data-anvia-thread-list-item": "",
130
- "data-active": item.active ? "" : void 0,
131
- "data-thread-id": item.thread.id
166
+ "data-state": item.active ? "active" : "inactive"
132
167
  },
133
- ref
168
+ composedRef
134
169
  );
135
170
  }
136
171
  );
@@ -138,7 +173,12 @@ var ThreadListItemTrigger = forwardRef(
138
173
  function ThreadListItemTrigger2({ onClick, ...props }, ref) {
139
174
  const threadList = useThreadList();
140
175
  const item = useThreadListItem();
176
+ const root = useInternalThreadListRoot();
141
177
  const disabled = props.disabled ?? false;
178
+ const composedRef = useMemo(
179
+ () => composeRefs(ref, (node) => root.registerTrigger(item.thread.id, node)),
180
+ [item.thread.id, ref, root]
181
+ );
142
182
  const handleClick = useCallback(
143
183
  (event) => {
144
184
  onClick?.(event);
@@ -158,10 +198,9 @@ var ThreadListItemTrigger = forwardRef(
158
198
  onClick: handleClick,
159
199
  type: props.type ?? "button",
160
200
  "aria-current": item.active ? "true" : void 0,
161
- "data-anvia-thread-list-trigger": "",
162
201
  "data-state": disabled ? "disabled" : "enabled"
163
202
  },
164
- ref
203
+ composedRef
165
204
  );
166
205
  }
167
206
  );
@@ -172,17 +211,17 @@ var ThreadListItemTitle = forwardRef(
172
211
  "span",
173
212
  {
174
213
  ...props,
175
- children: props.children ?? thread.title ?? fallback,
176
- "data-anvia-thread-list-title": ""
214
+ children: props.children ?? thread.title ?? fallback
177
215
  },
178
216
  ref
179
217
  );
180
218
  }
181
219
  );
182
- function createThreadListItemAction(action, defaultLabel, dataAttribute) {
220
+ function createThreadListItemAction(action, defaultLabel) {
183
221
  return forwardRef(function ThreadListItemAction({ onClick, ...props }, ref) {
184
222
  const threadList = useThreadList();
185
223
  const { thread } = useThreadListItem();
224
+ const root = useInternalThreadListRoot();
186
225
  const actionHandler = threadList[action];
187
226
  const disabled = props.disabled ?? actionHandler === void 0;
188
227
  const handleClick = useCallback(
@@ -191,10 +230,10 @@ function createThreadListItemAction(action, defaultLabel, dataAttribute) {
191
230
  if (event.defaultPrevented || disabled) {
192
231
  return;
193
232
  }
194
- focusAfterThreadItemRemoval(event.currentTarget);
233
+ focusAfterThreadItemRemoval(thread.id, root);
195
234
  void actionHandler?.(thread.id);
196
235
  },
197
- [actionHandler, disabled, onClick, thread.id]
236
+ [actionHandler, disabled, onClick, root, thread.id]
198
237
  );
199
238
  return renderPrimitive(
200
239
  "button",
@@ -204,28 +243,15 @@ function createThreadListItemAction(action, defaultLabel, dataAttribute) {
204
243
  disabled,
205
244
  onClick: handleClick,
206
245
  type: props.type ?? "button",
207
- [dataAttribute]: "",
208
246
  "data-state": disabled ? "disabled" : "enabled"
209
247
  },
210
248
  ref
211
249
  );
212
250
  });
213
251
  }
214
- var ThreadListItemArchive = createThreadListItemAction(
215
- "archiveThread",
216
- "Archive",
217
- "data-anvia-thread-list-archive"
218
- );
219
- var ThreadListItemUnarchive = createThreadListItemAction(
220
- "unarchiveThread",
221
- "Unarchive",
222
- "data-anvia-thread-list-unarchive"
223
- );
224
- var ThreadListItemDelete = createThreadListItemAction(
225
- "deleteThread",
226
- "Delete",
227
- "data-anvia-thread-list-delete"
228
- );
252
+ var ThreadListItemArchive = createThreadListItemAction("archiveThread", "Archive");
253
+ var ThreadListItemUnarchive = createThreadListItemAction("unarchiveThread", "Unarchive");
254
+ var ThreadListItemDelete = createThreadListItemAction("deleteThread", "Delete");
229
255
  function DefaultThreadItem() {
230
256
  return /* @__PURE__ */ jsx(ThreadListItemRoot, { children: /* @__PURE__ */ jsx(ThreadListItemTrigger, {}) });
231
257
  }
@@ -244,38 +270,37 @@ function nextTriggerIndex(key, currentIndex, triggerCount) {
244
270
  }
245
271
  return (currentIndex + 1) % triggerCount;
246
272
  }
247
- function focusAfterThreadItemRemoval(actionButton) {
248
- const root = actionButton.closest("[data-anvia-thread-list]");
249
- const currentItem = actionButton.closest("[data-anvia-thread-list-item]");
250
- if (root === null || currentItem === null || !currentItem.contains(root.ownerDocument.activeElement)) {
273
+ function focusAfterThreadItemRemoval(threadId, rootContext) {
274
+ const root = rootContext.rootRef.current;
275
+ const currentItem = rootContext.itemElements.current.get(threadId);
276
+ if (root === null || currentItem === void 0 || !currentItem.contains(root.ownerDocument.activeElement)) {
251
277
  return;
252
278
  }
253
- const triggers = Array.from(
254
- root.querySelectorAll("[data-anvia-thread-list-trigger]:not(:disabled)")
255
- );
256
- const currentTrigger = currentItem.querySelector(
257
- "[data-anvia-thread-list-trigger]"
258
- );
259
- const currentIndex = currentTrigger === null ? -1 : triggers.indexOf(currentTrigger);
279
+ const triggers = orderedEnabledTriggers(rootContext);
280
+ const currentTrigger = rootContext.triggerElements.current.get(threadId);
281
+ const currentIndex = currentTrigger === void 0 ? -1 : triggers.indexOf(currentTrigger);
260
282
  const remainingTriggers = triggers.filter((trigger) => !currentItem.contains(trigger));
261
- const fallback = root.querySelector(
262
- "[data-anvia-thread-list-new]:not(:disabled)"
263
- );
283
+ const fallback = rootContext.newButtonRef.current;
264
284
  const focusTarget = remainingTriggers[Math.min(Math.max(currentIndex, 0), remainingTriggers.length - 1)] ?? fallback ?? root;
265
285
  if (focusTarget === root && !root.hasAttribute("tabindex")) {
266
286
  root.tabIndex = -1;
267
287
  }
268
288
  focusTarget.focus();
269
289
  }
290
+ function orderedEnabledTriggers(rootContext) {
291
+ return [...rootContext.triggerElements.current.values()].filter((trigger) => trigger.isConnected && !trigger.disabled).sort(
292
+ (left, right) => left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
293
+ );
294
+ }
270
295
 
271
296
  // src/thread-list/index.ts
272
- var ThreadList = {
297
+ var ThreadListPrimitive = {
273
298
  Root: ThreadListRoot,
274
299
  New: ThreadListNew,
275
300
  Items: ThreadListItems,
276
301
  Empty: ThreadListEmpty
277
302
  };
278
- var ThreadListItem = {
303
+ var ThreadListItemPrimitive = {
279
304
  Root: ThreadListItemRoot,
280
305
  Trigger: ThreadListItemTrigger,
281
306
  Title: ThreadListItemTitle,
@@ -285,7 +310,7 @@ var ThreadListItem = {
285
310
  };
286
311
 
287
312
  export {
288
- ThreadList,
289
- ThreadListItem
313
+ ThreadListPrimitive,
314
+ ThreadListItemPrimitive
290
315
  };
291
- //# sourceMappingURL=chunk-OINUOCTO.js.map
316
+ //# sourceMappingURL=chunk-647LAYRV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/thread-list/parts.tsx","../src/thread-list/index.ts"],"sourcesContent":["import {\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\n\nimport {\n InternalThreadListItemProvider,\n InternalThreadListRootProvider,\n type ThreadListRecord,\n useInternalThreadListRoot,\n useThreadList,\n useThreadListItem,\n} from \"../contexts\";\nimport { composeRefs, type PrimitiveProps, renderPrimitive } from \"../primitives\";\n\ntype ThreadListRootProps = PrimitiveProps<\"div\">;\n\nconst ThreadListRoot = forwardRef<HTMLDivElement, ThreadListRootProps>(function ThreadListRoot(\n { onKeyDown, ...props },\n ref,\n) {\n const threadList = useThreadList();\n const rootRef = useRef<HTMLDivElement | null>(null);\n const newButtonRef = useRef<HTMLButtonElement | null>(null);\n const itemElements = useRef(new Map<string, HTMLDivElement>());\n const triggerElements = useRef(new Map<string, HTMLButtonElement>());\n const registerItem = useCallback((threadId: string, element: HTMLDivElement | null) => {\n if (element === null) itemElements.current.delete(threadId);\n else itemElements.current.set(threadId, element);\n }, []);\n const registerTrigger = useCallback((threadId: string, element: HTMLButtonElement | null) => {\n if (element === null) triggerElements.current.delete(threadId);\n else triggerElements.current.set(threadId, element);\n }, []);\n const rootContext = useMemo(\n () => ({\n rootRef,\n newButtonRef,\n itemElements,\n triggerElements,\n registerItem,\n registerTrigger,\n }),\n [registerItem, registerTrigger],\n );\n const composedRef = useMemo(\n () =>\n composeRefs<HTMLDivElement>(ref, (node) => {\n rootRef.current = node;\n }),\n [ref],\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented || ![\"ArrowDown\", \"ArrowUp\", \"Home\", \"End\"].includes(event.key)) {\n return;\n }\n const triggers = orderedEnabledTriggers(rootContext);\n if (triggers.length === 0) {\n return;\n }\n event.preventDefault();\n const activeElement = document.activeElement;\n const currentIndex =\n activeElement instanceof HTMLButtonElement ? triggers.indexOf(activeElement) : -1;\n const nextIndex = nextTriggerIndex(event.key, currentIndex, triggers.length);\n triggers[nextIndex]?.focus();\n },\n [onKeyDown, rootContext],\n );\n\n return (\n <InternalThreadListRootProvider value={rootContext}>\n {renderPrimitive(\n \"div\",\n {\n ...props,\n onKeyDown: handleKeyDown,\n \"data-state\": threadList.status ?? \"idle\",\n } as PrimitiveProps<\"div\">,\n composedRef,\n )}\n </InternalThreadListRootProvider>\n );\n});\n\nconst ThreadListNew = forwardRef<HTMLButtonElement, PrimitiveProps<\"button\">>(\n function ThreadListNew({ onClick, ...props }, ref) {\n const threadList = useThreadList();\n const root = useInternalThreadListRoot();\n const composedRef = useMemo(\n () =>\n composeRefs<HTMLButtonElement>(ref, (node) => {\n root.newButtonRef.current = node;\n }),\n [ref, root.newButtonRef],\n );\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || props.disabled) {\n return;\n }\n void threadList.createThread();\n },\n [onClick, props.disabled, threadList],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? \"New chat\",\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"data-state\": props.disabled ? \"disabled\" : \"enabled\",\n } as PrimitiveProps<\"button\">,\n composedRef,\n );\n },\n);\n\ntype ThreadListItemsChildren = ReactNode | ((thread: ThreadListRecord) => ReactNode);\n\ntype ThreadListItemsProps = Omit<PrimitiveProps<\"div\">, \"children\"> & {\n archived?: boolean;\n children?: ThreadListItemsChildren;\n keepMounted?: boolean;\n};\n\nconst ThreadListItems = forwardRef<HTMLDivElement, ThreadListItemsProps>(function ThreadListItems(\n { archived = false, children, keepMounted = false, ...props },\n ref,\n) {\n const threadList = useThreadList();\n const threads = threadList.threads.filter((thread) => Boolean(thread.archived) === archived);\n const empty = threads.length === 0;\n if (empty && !keepMounted) {\n return null;\n }\n\n return renderPrimitive(\n \"div\",\n {\n ...props,\n children: threads.map((thread) => (\n <InternalThreadListItemProvider\n key={thread.id}\n value={{ thread, active: thread.id === threadList.activeThreadId }}\n >\n {typeof children === \"function\" ? children(thread) : (children ?? <DefaultThreadItem />)}\n </InternalThreadListItemProvider>\n )),\n \"data-state\": empty ? \"empty\" : \"populated\",\n } as PrimitiveProps<\"div\">,\n ref,\n );\n});\n\ntype ThreadListEmptyProps = PrimitiveProps<\"div\"> & {\n archived?: boolean;\n};\n\nconst ThreadListEmpty = forwardRef<HTMLDivElement, ThreadListEmptyProps>(function ThreadListEmpty(\n { archived = false, ...props },\n ref,\n) {\n const threadList = useThreadList();\n const hasVisibleThreads = threadList.threads.some(\n (thread) => Boolean(thread.archived) === archived,\n );\n if (hasVisibleThreads) {\n return null;\n }\n\n return renderPrimitive(\n \"div\",\n {\n ...props,\n children: props.children ?? \"No conversations.\",\n } as PrimitiveProps<\"div\">,\n ref,\n );\n});\n\nconst ThreadListItemRoot = forwardRef<HTMLDivElement, PrimitiveProps<\"div\">>(\n function ThreadListItemRoot(props, ref) {\n const item = useThreadListItem();\n const root = useInternalThreadListRoot();\n const composedRef = useMemo(\n () => composeRefs<HTMLDivElement>(ref, (node) => root.registerItem(item.thread.id, node)),\n [item.thread.id, ref, root],\n );\n\n return renderPrimitive(\n \"div\",\n {\n ...props,\n \"data-state\": item.active ? \"active\" : \"inactive\",\n } as PrimitiveProps<\"div\">,\n composedRef,\n );\n },\n);\n\nconst ThreadListItemTrigger = forwardRef<HTMLButtonElement, PrimitiveProps<\"button\">>(\n function ThreadListItemTrigger({ onClick, ...props }, ref) {\n const threadList = useThreadList();\n const item = useThreadListItem();\n const root = useInternalThreadListRoot();\n const disabled = props.disabled ?? false;\n const composedRef = useMemo(\n () =>\n composeRefs<HTMLButtonElement>(ref, (node) => root.registerTrigger(item.thread.id, node)),\n [item.thread.id, ref, root],\n );\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || disabled) {\n return;\n }\n void threadList.switchThread(item.thread.id);\n },\n [disabled, item.thread.id, onClick, threadList],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? <ThreadListItemTitle />,\n disabled,\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"aria-current\": item.active ? \"true\" : undefined,\n \"data-state\": disabled ? \"disabled\" : \"enabled\",\n } as PrimitiveProps<\"button\">,\n composedRef,\n );\n },\n);\n\ntype ThreadListItemTitleProps = PrimitiveProps<\"span\"> & {\n fallback?: ReactNode;\n};\n\nconst ThreadListItemTitle = forwardRef<HTMLSpanElement, ThreadListItemTitleProps>(\n function ThreadListItemTitle({ fallback = \"New chat\", ...props }, ref) {\n const { thread } = useThreadListItem();\n\n return renderPrimitive(\n \"span\",\n {\n ...props,\n children: props.children ?? thread.title ?? fallback,\n } as PrimitiveProps<\"span\">,\n ref,\n );\n },\n);\n\ntype ThreadListItemActionKey = \"archiveThread\" | \"unarchiveThread\" | \"deleteThread\";\nfunction createThreadListItemAction(action: ThreadListItemActionKey, defaultLabel: string) {\n return forwardRef<HTMLButtonElement, PrimitiveProps<\"button\">>(function ThreadListItemAction(\n { onClick, ...props },\n ref,\n ) {\n const threadList = useThreadList();\n const { thread } = useThreadListItem();\n const root = useInternalThreadListRoot();\n const actionHandler = threadList[action];\n const disabled = props.disabled ?? actionHandler === undefined;\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || disabled) {\n return;\n }\n focusAfterThreadItemRemoval(thread.id, root);\n void actionHandler?.(thread.id);\n },\n [actionHandler, disabled, onClick, root, thread.id],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? defaultLabel,\n disabled,\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"data-state\": disabled ? \"disabled\" : \"enabled\",\n } as PrimitiveProps<\"button\">,\n ref,\n );\n });\n}\n\nconst ThreadListItemArchive = createThreadListItemAction(\"archiveThread\", \"Archive\");\nconst ThreadListItemUnarchive = createThreadListItemAction(\"unarchiveThread\", \"Unarchive\");\nconst ThreadListItemDelete = createThreadListItemAction(\"deleteThread\", \"Delete\");\n\nfunction DefaultThreadItem(): ReactNode {\n return (\n <ThreadListItemRoot>\n <ThreadListItemTrigger />\n </ThreadListItemRoot>\n );\n}\n\nfunction nextTriggerIndex(key: string, currentIndex: number, triggerCount: number): number {\n if (key === \"Home\") {\n return 0;\n }\n if (key === \"End\") {\n return triggerCount - 1;\n }\n if (currentIndex === -1) {\n return key === \"ArrowUp\" ? triggerCount - 1 : 0;\n }\n if (key === \"ArrowUp\") {\n return (currentIndex - 1 + triggerCount) % triggerCount;\n }\n return (currentIndex + 1) % triggerCount;\n}\n\nfunction focusAfterThreadItemRemoval(\n threadId: string,\n rootContext: ReturnType<typeof useInternalThreadListRoot>,\n): void {\n const root = rootContext.rootRef.current;\n const currentItem = rootContext.itemElements.current.get(threadId);\n if (\n root === null ||\n currentItem === undefined ||\n !currentItem.contains(root.ownerDocument.activeElement)\n ) {\n return;\n }\n\n const triggers = orderedEnabledTriggers(rootContext);\n const currentTrigger = rootContext.triggerElements.current.get(threadId);\n const currentIndex = currentTrigger === undefined ? -1 : triggers.indexOf(currentTrigger);\n const remainingTriggers = triggers.filter((trigger) => !currentItem.contains(trigger));\n const fallback = rootContext.newButtonRef.current;\n const focusTarget =\n remainingTriggers[Math.min(Math.max(currentIndex, 0), remainingTriggers.length - 1)] ??\n fallback ??\n root;\n\n if (focusTarget === root && !root.hasAttribute(\"tabindex\")) {\n root.tabIndex = -1;\n }\n focusTarget.focus();\n}\n\nfunction orderedEnabledTriggers(\n rootContext: ReturnType<typeof useInternalThreadListRoot>,\n): HTMLButtonElement[] {\n return [...rootContext.triggerElements.current.values()]\n .filter((trigger) => trigger.isConnected && !trigger.disabled)\n .sort((left, right) =>\n left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1,\n );\n}\n\nexport {\n ThreadListEmpty,\n ThreadListItemArchive,\n ThreadListItemDelete,\n ThreadListItemRoot,\n ThreadListItems,\n ThreadListItemTitle,\n ThreadListItemTrigger,\n ThreadListItemUnarchive,\n ThreadListNew,\n ThreadListRoot,\n};\n","import {\n ThreadListEmpty,\n ThreadListItemArchive,\n ThreadListItemDelete,\n ThreadListItemRoot,\n ThreadListItems,\n ThreadListItemTitle,\n ThreadListItemTrigger,\n ThreadListItemUnarchive,\n ThreadListNew,\n ThreadListRoot,\n} from \"./parts\";\n\nexport const ThreadListPrimitive = {\n Root: ThreadListRoot,\n New: ThreadListNew,\n Items: ThreadListItems,\n Empty: ThreadListEmpty,\n} as const;\n\nexport const ThreadListItemPrimitive = {\n Root: ThreadListItemRoot,\n Trigger: ThreadListItemTrigger,\n Title: ThreadListItemTitle,\n Archive: ThreadListItemArchive,\n Unarchive: ThreadListItemUnarchive,\n Delete: ThreadListItemDelete,\n} as const;\n\nexport type {\n ThreadListController,\n ThreadListItemContextValue,\n ThreadListProviderProps,\n ThreadListRecord,\n} from \"../contexts\";\nexport { ThreadListProvider, useThreadList, useThreadListItem } from \"../contexts\";\n"],"mappings":"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","names":["ThreadListRoot","ThreadListNew","ThreadListItems","ThreadListEmpty","ThreadListItemRoot","ThreadListItemTrigger","ThreadListItemTitle"]}
@@ -0,0 +1,22 @@
1
+ // src/message/elements.ts
2
+ var messageIds = /* @__PURE__ */ new WeakMap();
3
+ function registerMessageElement(element, messageId) {
4
+ messageIds.set(element, messageId);
5
+ }
6
+ function messageElementFromNode(node) {
7
+ let element = node?.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement ?? void 0;
8
+ while (element !== void 0 && element !== null) {
9
+ const messageId = messageIds.get(element);
10
+ if (messageId !== void 0) {
11
+ return { element, messageId };
12
+ }
13
+ element = element.parentElement ?? void 0;
14
+ }
15
+ return void 0;
16
+ }
17
+
18
+ export {
19
+ registerMessageElement,
20
+ messageElementFromNode
21
+ };
22
+ //# sourceMappingURL=chunk-6XOJFLX4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/message/elements.ts"],"sourcesContent":["const messageIds = new WeakMap<HTMLElement, string>();\n\nexport function registerMessageElement(element: HTMLElement, messageId: string): void {\n messageIds.set(element, messageId);\n}\n\nexport function messageElementFromNode(\n node: Node | null,\n): { element: HTMLElement; messageId: string } | undefined {\n let element =\n node?.nodeType === Node.ELEMENT_NODE\n ? (node as HTMLElement)\n : (node?.parentElement ?? undefined);\n\n while (element !== undefined && element !== null) {\n const messageId = messageIds.get(element);\n if (messageId !== undefined) {\n return { element, messageId };\n }\n element = element.parentElement ?? undefined;\n }\n return undefined;\n}\n"],"mappings":";AAAA,IAAM,aAAa,oBAAI,QAA6B;AAE7C,SAAS,uBAAuB,SAAsB,WAAyB;AACpF,aAAW,IAAI,SAAS,SAAS;AACnC;AAEO,SAAS,uBACd,MACyD;AACzD,MAAI,UACF,MAAM,aAAa,KAAK,eACnB,OACA,MAAM,iBAAiB;AAE9B,SAAO,YAAY,UAAa,YAAY,MAAM;AAChD,UAAM,YAAY,WAAW,IAAI,OAAO;AACxC,QAAI,cAAc,QAAW;AAC3B,aAAO,EAAE,SAAS,UAAU;AAAA,IAC9B;AACA,cAAU,QAAQ,iBAAiB;AAAA,EACrC;AACA,SAAO;AACT;","names":[]}