@nonoun/native-chat 0.5.7 → 0.5.8
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.
- package/README.md +332 -0
- package/dist/{chat-input-structured-element-Bt9nkgXp.js → chat-input-structured-element-DPKHlnRm.js} +20 -17
- package/dist/message/chat-message-element.d.ts.map +1 -1
- package/dist/native-chat.css +24 -1
- package/dist/native-chat.js +1 -1
- package/dist/register.js +1 -1
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# @nonoun/native-chat
|
|
2
|
+
|
|
3
|
+
Chat UI components for `@nonoun/native-ui` — message feed, composer input, streaming transport, and a top-level panel with imperative host-integration APIs.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @nonoun/native-chat @nonoun/native-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<link rel="stylesheet" href="node_modules/@nonoun/native-ui/dist/native-ui.css" />
|
|
15
|
+
<link rel="stylesheet" href="node_modules/@nonoun/native-chat/dist/native-chat.css" />
|
|
16
|
+
|
|
17
|
+
<script type="module">
|
|
18
|
+
import '@nonoun/native-ui/register';
|
|
19
|
+
import '@nonoun/native-chat/register';
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<native-chat-panel auto-focus-policy="open-request">
|
|
23
|
+
<!-- panel stamps its own children: header, feed, composer -->
|
|
24
|
+
</native-chat-panel>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Components
|
|
28
|
+
|
|
29
|
+
| Element | Description |
|
|
30
|
+
|---------|-------------|
|
|
31
|
+
| `native-chat-panel` | Top-level panel — owns lifecycle, focus policy, header actions |
|
|
32
|
+
| `n-chat-feed` | Scrollable message feed with optional virtualization |
|
|
33
|
+
| `n-chat-messages` | Message list wrapper (inside feed) |
|
|
34
|
+
| `n-chat-message` | Single message container with role, status, actions |
|
|
35
|
+
| `n-chat-message-text` | Markdown-rendered text bubble |
|
|
36
|
+
| `n-chat-message-activity` | Typing / system activity indicator |
|
|
37
|
+
| `n-chat-message-seed` | Seed prompt card |
|
|
38
|
+
| `n-chat-message-genui` | Generative UI node renderer |
|
|
39
|
+
| `n-chat-avatar` | Message avatar |
|
|
40
|
+
| `n-chat-input` | Composer with submit, formatting, slash commands |
|
|
41
|
+
| `n-chat-input-structured` | Multi-option structured input picker |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Embedding Guide
|
|
46
|
+
|
|
47
|
+
### Panel Host API
|
|
48
|
+
|
|
49
|
+
`native-chat-panel` exposes three imperative methods for host orchestration:
|
|
50
|
+
|
|
51
|
+
#### `open(options?)`
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
panel.open();
|
|
55
|
+
panel.open({ focusComposer: true, reason: 'deeplink' });
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
| Option | Type | Default | Description |
|
|
59
|
+
|--------|------|---------|-------------|
|
|
60
|
+
| `focusComposer` | `boolean` | `false` | Request composer focus after opening |
|
|
61
|
+
| `reason` | `string` | — | Why the panel opened (telemetry / debugging) |
|
|
62
|
+
|
|
63
|
+
Sets the `[open]` attribute. Idempotent — calling `open()` when already open does not re-emit events.
|
|
64
|
+
|
|
65
|
+
#### `close(reason?)`
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
panel.close();
|
|
69
|
+
panel.close('user-dismiss');
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Removes the `[open]` attribute. Idempotent.
|
|
73
|
+
|
|
74
|
+
#### `focusComposer(options?, by?)`
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
panel.focusComposer();
|
|
78
|
+
panel.focusComposer({ cursor: 'end' }, 'api');
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
| Option | Type | Default | Description |
|
|
82
|
+
|--------|------|---------|-------------|
|
|
83
|
+
| `cursor` | `'start' \| 'end' \| 'preserve'` | `'end'` | Caret placement after focus |
|
|
84
|
+
| `by` | `'api' \| 'user' \| 'policy'` | `'api'` | Focus source (included in events) |
|
|
85
|
+
|
|
86
|
+
Retries up to 3 times via microtask if the composer is not yet available or disabled. On success dispatches `native:composer-focused`; on failure dispatches `native:composer-focus-failed`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Lifecycle Events
|
|
91
|
+
|
|
92
|
+
All events bubble and are composed (cross shadow DOM). Listen on the panel or any ancestor:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const panel = document.querySelector('native-chat-panel');
|
|
96
|
+
|
|
97
|
+
panel.addEventListener('native:chat-opened', (e) => {
|
|
98
|
+
console.log('opened', e.detail.source, e.detail.focusComposer);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
panel.addEventListener('native:chat-closed', (e) => {
|
|
102
|
+
console.log('closed', e.detail.reason);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
panel.addEventListener('native:send', (e) => {
|
|
106
|
+
console.log('user sent:', e.detail.value);
|
|
107
|
+
// Call e.preventDefault() to block auto-clear
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
| Event | Detail | Notes |
|
|
112
|
+
|-------|--------|-------|
|
|
113
|
+
| `native:chat-opened` | `{ source?: string, focusComposer: boolean }` | After panel opens |
|
|
114
|
+
| `native:chat-closed` | `{ reason?: string }` | After panel closes |
|
|
115
|
+
| `native:composer-focused` | `{ by: 'api' \| 'user' \| 'policy' }` | Composer received focus |
|
|
116
|
+
| `native:composer-focus-failed` | `{ reason: string, attempts: number }` | All focus retries exhausted |
|
|
117
|
+
| `native:send` | `{ value: string }` | User submitted message (**cancelable**) |
|
|
118
|
+
| `native:chat-stop` | — | User clicked stop button |
|
|
119
|
+
| `native:chat-restart` | — | User clicked restart button |
|
|
120
|
+
| `native:message-action` | `{ action: string, messageId: string }` | Message action triggered |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Focus Policy
|
|
125
|
+
|
|
126
|
+
The `auto-focus-policy` attribute controls when the composer auto-focuses:
|
|
127
|
+
|
|
128
|
+
| Value | Behavior |
|
|
129
|
+
|-------|----------|
|
|
130
|
+
| `open-request` (default) | Focus composer only when `open({ focusComposer: true })` is called |
|
|
131
|
+
| `ready` | Auto-focus once at panel initialization |
|
|
132
|
+
| `never` | Never auto-focus — host must call `focusComposer()` explicitly |
|
|
133
|
+
|
|
134
|
+
**Recommended default:** `open-request` — gives the host full control over focus timing.
|
|
135
|
+
|
|
136
|
+
#### Focus Failure Handling
|
|
137
|
+
|
|
138
|
+
When `focusComposer()` cannot reach the textarea (not rendered, disabled, or blocked), the panel emits `native:composer-focus-failed` after 3 retry attempts:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
panel.addEventListener('native:composer-focus-failed', (e) => {
|
|
142
|
+
const { reason, attempts } = e.detail;
|
|
143
|
+
// reason: 'composer-unavailable' | 'disabled' | 'blocked'
|
|
144
|
+
// Show a fallback hint or retry button
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Recommended UX:** Keep the panel open, show a subtle status hint, and let the user retry manually.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
### Host Orchestration Patterns
|
|
153
|
+
|
|
154
|
+
#### Deeplink
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
// Parse URL: ?openChat=1
|
|
158
|
+
if (new URLSearchParams(location.search).has('openChat')) {
|
|
159
|
+
panel.open({ focusComposer: true, reason: 'deeplink' });
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### Notification or External Action
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
notificationButton.addEventListener('click', () => {
|
|
167
|
+
panel.open({ focusComposer: false, reason: 'notification' });
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Intercepting Send
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
panel.addEventListener('native:send', (e) => {
|
|
175
|
+
const { value } = e.detail;
|
|
176
|
+
if (!value.trim()) {
|
|
177
|
+
e.preventDefault(); // block auto-clear, ignore empty
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
myTransport.send(value);
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### Transport Error & Retry
|
|
187
|
+
|
|
188
|
+
`createChatTransport()` provides a streaming transport layer with built-in error classification and retry logic.
|
|
189
|
+
|
|
190
|
+
#### Transport States
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
idle → sending → streaming → ready
|
|
194
|
+
↘ retrying → sending (retry loop)
|
|
195
|
+
↘ rate-limited (429)
|
|
196
|
+
↘ auth-required (401/403)
|
|
197
|
+
↘ server-error (5xx / network)
|
|
198
|
+
↘ offline (DNS / TypeError)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### Usage
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { createChatTransport } from '@nonoun/native-chat';
|
|
205
|
+
|
|
206
|
+
const transport = createChatTransport({
|
|
207
|
+
baseUrl: '/api/chat',
|
|
208
|
+
format: 'sse',
|
|
209
|
+
retry: { maxAttempts: 3, baseDelayMs: 1000, maxDelayMs: 30000 },
|
|
210
|
+
onStateChange(status) {
|
|
211
|
+
// status: { state, statusCode?, retryInMs?, attempt?, maxAttempts?, error? }
|
|
212
|
+
switch (status.state) {
|
|
213
|
+
case 'sending': showSpinner(); break;
|
|
214
|
+
case 'streaming': hideSpinner(); break;
|
|
215
|
+
case 'retrying': showRetryBanner(status.retryInMs); break;
|
|
216
|
+
case 'rate-limited': showRateLimitNotice(status.retryInMs); break;
|
|
217
|
+
case 'auth-required': redirectToLogin(); break;
|
|
218
|
+
case 'server-error': showErrorBanner(status.error); break;
|
|
219
|
+
case 'offline': showOfflineBanner(); break;
|
|
220
|
+
case 'ready': clearAllBanners(); break;
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Defaults & Behavior
|
|
227
|
+
|
|
228
|
+
| Behavior | Default |
|
|
229
|
+
|----------|---------|
|
|
230
|
+
| Retry | Disabled (`maxAttempts: 1`) |
|
|
231
|
+
| Retryable errors | 429 (rate-limited), 5xx (server error) |
|
|
232
|
+
| Non-retryable | 401/403 (auth-required) — never retried |
|
|
233
|
+
| 429 delay | Respects `Retry-After` header (seconds or HTTP-date) |
|
|
234
|
+
| Backoff | Exponential: `min(maxDelay, baseDelay * 2^attempt + jitter)` |
|
|
235
|
+
| Stream formats | `'sse'`, `'ndjson'`, `'json'` (auto-detected via `detectFormat()`) |
|
|
236
|
+
|
|
237
|
+
#### Stream End Classification
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
import { classifyStreamEnd } from '@nonoun/native-chat';
|
|
241
|
+
|
|
242
|
+
// Returns: 'complete' | 'partial' | 'error' | 'stopped'
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
| Reason | Meaning |
|
|
246
|
+
|--------|---------|
|
|
247
|
+
| `complete` | Server sent explicit done signal |
|
|
248
|
+
| `partial` | Stream ended without completion (truncated) |
|
|
249
|
+
| `error` | Transport or parse error |
|
|
250
|
+
| `stopped` | Consumer aborted (user clicked stop) |
|
|
251
|
+
|
|
252
|
+
Use `partial` status on messages to offer a "Continue" action.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### Message Actions
|
|
257
|
+
|
|
258
|
+
Messages show contextual action buttons (copy, regenerate, edit, feedback):
|
|
259
|
+
|
|
260
|
+
```html
|
|
261
|
+
<n-chat-message role="assistant" actions="copy,regenerate,thumbs-up,thumbs-down">
|
|
262
|
+
<n-chat-message-text>Hello!</n-chat-message-text>
|
|
263
|
+
</n-chat-message>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
| Attribute | Values | Default |
|
|
267
|
+
|-----------|--------|---------|
|
|
268
|
+
| `actions` | Comma-separated action IDs, or `"none"` | Role-based defaults |
|
|
269
|
+
| `actions-style` | `'icon' \| 'label' \| 'icon-label'` | `'icon'` |
|
|
270
|
+
| `actions-position` | `'below' \| 'inside'` | `'below'` |
|
|
271
|
+
|
|
272
|
+
Listen for actions on any ancestor:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
panel.addEventListener('native:message-action', (e) => {
|
|
276
|
+
const { action, messageId } = e.detail;
|
|
277
|
+
if (action === 'copy') navigator.clipboard.writeText(getMessageText(messageId));
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### Feed Virtualization
|
|
284
|
+
|
|
285
|
+
For long transcripts, enable virtual scrolling on the feed:
|
|
286
|
+
|
|
287
|
+
```html
|
|
288
|
+
<n-chat-feed virtual virtual-item-height="80" virtual-overscan="5">
|
|
289
|
+
<n-chat-messages>...</n-chat-messages>
|
|
290
|
+
</n-chat-feed>
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Only visible items (plus overscan buffer) are rendered. The feed emits `native:range-change` with `{ start, end, total }` as the viewport scrolls.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Exports
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
// Components
|
|
301
|
+
import {
|
|
302
|
+
NChatPanel, NChatInput, NChatFeed, NChatMessage,
|
|
303
|
+
NChatMessages, NChatMessageText, NChatMessageActivity,
|
|
304
|
+
NChatAvatar, NChatMessageSeed, NChatMessageGenUI,
|
|
305
|
+
NChatInputStructured,
|
|
306
|
+
} from '@nonoun/native-chat';
|
|
307
|
+
|
|
308
|
+
// Stream / Transport
|
|
309
|
+
import {
|
|
310
|
+
createChatTransport, createChatStream,
|
|
311
|
+
parseSSE, parseNDJSON, parseJSON, detectFormat,
|
|
312
|
+
classifyHttpError, classifyStreamEnd, backoffDelay,
|
|
313
|
+
} from '@nonoun/native-chat';
|
|
314
|
+
|
|
315
|
+
// Types
|
|
316
|
+
import type {
|
|
317
|
+
AutoFocusPolicy, ChatPanelOpenOptions, FocusComposerOptions,
|
|
318
|
+
ChatTransportOptions, TransportState, TransportStatus, RetryOptions,
|
|
319
|
+
ChatStreamEvent, ChatStreamChunk, StreamFormat, StreamEndReason,
|
|
320
|
+
} from '@nonoun/native-chat';
|
|
321
|
+
|
|
322
|
+
// Utilities
|
|
323
|
+
import { renderMarkdown, renderInline, sanitizeHtml } from '@nonoun/native-chat';
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Peer Dependency
|
|
327
|
+
|
|
328
|
+
Requires `@nonoun/native-ui >= 0.6.0`.
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
MIT
|
package/dist/{chat-input-structured-element-Bt9nkgXp.js → chat-input-structured-element-DPKHlnRm.js}
RENAMED
|
@@ -594,6 +594,7 @@ var p = class extends e {
|
|
|
594
594
|
#o = null;
|
|
595
595
|
#s = !1;
|
|
596
596
|
#c = 0;
|
|
597
|
+
#l = 0;
|
|
597
598
|
constructor() {
|
|
598
599
|
super(), this.#e = this.attachInternals();
|
|
599
600
|
}
|
|
@@ -656,40 +657,42 @@ var p = class extends e {
|
|
|
656
657
|
}
|
|
657
658
|
}
|
|
658
659
|
setup() {
|
|
659
|
-
super.setup(), this.addEventListener("pointerenter", this.#
|
|
660
|
+
super.setup(), this.addEventListener("pointerenter", this.#u), this.addEventListener("pointerleave", this.#d), this.addEffect(() => {
|
|
660
661
|
let e = this.#t.value, t = this.#r.value, n = this.#i.value, r = this.#a.value, i = this.#n.value;
|
|
661
|
-
this.#
|
|
662
|
+
this.#p(e, t, n, r, i);
|
|
662
663
|
}), this.#e.role = "article";
|
|
663
664
|
}
|
|
664
665
|
teardown() {
|
|
665
|
-
this.removeEventListener("pointerenter", this.#
|
|
666
|
+
this.removeEventListener("pointerenter", this.#u), this.removeEventListener("pointerleave", this.#d), clearTimeout(this.#c), clearTimeout(this.#l), this.#o &&= (this.#f(), null), super.teardown();
|
|
666
667
|
}
|
|
667
|
-
#l = () => {
|
|
668
|
-
if (clearTimeout(this.#c), this.#o && this.#s && this.#n.value !== "partial") try {
|
|
669
|
-
this.#o.showPopover();
|
|
670
|
-
} catch {}
|
|
671
|
-
};
|
|
672
668
|
#u = () => {
|
|
673
|
-
!this.#s || this.#n.value === "partial"
|
|
669
|
+
clearTimeout(this.#l), !(!this.#o || !this.#s || this.#n.value === "partial") && (clearTimeout(this.#c), this.#c = window.setTimeout(() => {
|
|
670
|
+
try {
|
|
671
|
+
this.#o?.showPopover();
|
|
672
|
+
} catch {}
|
|
673
|
+
}, 300));
|
|
674
|
+
};
|
|
675
|
+
#d = () => {
|
|
676
|
+
!this.#s || this.#n.value === "partial" || (clearTimeout(this.#c), clearTimeout(this.#l), this.#l = window.setTimeout(() => {
|
|
674
677
|
try {
|
|
675
678
|
this.#o?.hidePopover();
|
|
676
679
|
} catch {}
|
|
677
680
|
}, 150));
|
|
678
681
|
};
|
|
679
|
-
#
|
|
682
|
+
#f() {
|
|
680
683
|
if (this.#o) {
|
|
681
684
|
if (this.#s) {
|
|
682
|
-
this.#o.removeEventListener("pointerenter", this.#
|
|
685
|
+
this.#o.removeEventListener("pointerenter", this.#u), this.#o.removeEventListener("pointerleave", this.#d), this.#o.removeEventListener("focusin", this.#u), this.#o.removeEventListener("focusout", this.#d);
|
|
683
686
|
try {
|
|
684
687
|
this.#o.hidePopover();
|
|
685
688
|
} catch {}
|
|
686
689
|
this.style.removeProperty("anchor-name"), this.#s = !1;
|
|
687
690
|
}
|
|
688
|
-
this.#o.removeEventListener("native:press", this.#
|
|
691
|
+
this.#o.removeEventListener("native:press", this.#m), this.#o.remove();
|
|
689
692
|
}
|
|
690
693
|
}
|
|
691
|
-
#
|
|
692
|
-
if (this.#o &&= (this.#
|
|
694
|
+
#p(e, t, n, r, a) {
|
|
695
|
+
if (this.#o &&= (this.#f(), null), clearTimeout(this.#l), t === "none" || this.querySelector("[slot=\"actions\"]")) return;
|
|
693
696
|
let o;
|
|
694
697
|
if (o = t ? t.split(",").map((e) => e.trim()).filter(Boolean) : f[e] ?? [], a === "partial" && !o.includes("continue") && (o = [...o, "continue"]), o.length === 0) return;
|
|
695
698
|
let s = document.createElement("n-toolbar");
|
|
@@ -699,15 +702,15 @@ var p = class extends e {
|
|
|
699
702
|
t && s.appendChild(m(e, t, n));
|
|
700
703
|
}
|
|
701
704
|
if (s.children.length !== 0) {
|
|
702
|
-
if (s.addEventListener("native:press", this.#
|
|
705
|
+
if (s.addEventListener("native:press", this.#m), r === "below") {
|
|
703
706
|
s.setAttribute("popover", "manual");
|
|
704
707
|
let e = i("msg");
|
|
705
|
-
this.style.setProperty("anchor-name", `--${e}`), s.style.setProperty("position-anchor", `--${e}`), this.appendChild(s), this.#s = !0, s.addEventListener("pointerenter", this.#
|
|
708
|
+
this.style.setProperty("anchor-name", `--${e}`), s.style.setProperty("position-anchor", `--${e}`), this.appendChild(s), this.#s = !0, s.addEventListener("pointerenter", this.#u), s.addEventListener("pointerleave", this.#d), s.addEventListener("focusin", this.#u), s.addEventListener("focusout", this.#d), a === "partial" && s.showPopover();
|
|
706
709
|
} else this.appendChild(s);
|
|
707
710
|
this.#o = s;
|
|
708
711
|
}
|
|
709
712
|
}
|
|
710
|
-
#
|
|
713
|
+
#m = (e) => {
|
|
711
714
|
let t = e.target?.getAttribute("data-action");
|
|
712
715
|
if (t) {
|
|
713
716
|
if (e.stopPropagation(), t === "continue") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-message-element.d.ts","sourceRoot":"","sources":["../../src/message/chat-message-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAI/D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAOhE,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAGlD,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,aAAa;;IAC7C,MAAM,CAAC,kBAAkB,WAAiG;;
|
|
1
|
+
{"version":3,"file":"chat-message-element.d.ts","sourceRoot":"","sources":["../../src/message/chat-message-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAe,MAAM,mBAAmB,CAAC;AAI/D,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAOhE,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAGlD,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAa,SAAQ,aAAa;;IAC7C,MAAM,CAAC,kBAAkB,WAAiG;;IAoB1H,IAAI,IAAI,IAAI,MAAM,CAA6B;IAC/C,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,EAGnB;IAED,IAAI,SAAS,IAAI,MAAM,CAAkD;IAEzE,IAAI,SAAS,IAAI,MAAM,CAAwD;IAE/E,IAAI,MAAM,IAAI,MAAM,CAA+B;IACnD,IAAI,MAAM,CAAC,GAAG,EAAE,MAAM,EAGrB;IAED,IAAI,OAAO,IAAI,MAAM,GAAG,IAAI,CAAgC;IAC5D,IAAI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAO7B;IAED,IAAI,YAAY,IAAI,MAAM,CAAqC;IAC/D,IAAI,YAAY,CAAC,GAAG,EAAE,MAAM,EAG3B;IAED,IAAI,eAAe,IAAI,MAAM,CAAwC;IACrE,IAAI,eAAe,CAAC,GAAG,EAAE,MAAM,EAG9B;IAID,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAcpF,KAAK,IAAI,IAAI;IAqBb,QAAQ,IAAI,IAAI;CAoJjB"}
|
package/dist/native-chat.css
CHANGED
|
@@ -384,7 +384,8 @@
|
|
|
384
384
|
|
|
385
385
|
/* Popover toolbar: anchored below the message via CSS anchor positioning.
|
|
386
386
|
Toolbar is a child of n-chat-message with popover="manual", rendered in the
|
|
387
|
-
top layer. JS shows/hides via pointerenter/pointerleave + showPopover().
|
|
387
|
+
top layer. JS shows/hides via pointerenter/pointerleave + showPopover().
|
|
388
|
+
Entry/exit transition mirrors n-listbox[popover] (perspective + scale). */
|
|
388
389
|
:where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]) {
|
|
389
390
|
position: fixed;
|
|
390
391
|
inset: auto;
|
|
@@ -393,6 +394,28 @@
|
|
|
393
394
|
translate: -50% 0;
|
|
394
395
|
margin: 2px 0 0;
|
|
395
396
|
width: max-content;
|
|
397
|
+
|
|
398
|
+
transform-origin: top center;
|
|
399
|
+
opacity: 0;
|
|
400
|
+
transform: perspective(800px) scale(0.96) rotateX(-20deg);
|
|
401
|
+
|
|
402
|
+
transition:
|
|
403
|
+
opacity var(--n-duration) var(--n-easing),
|
|
404
|
+
transform var(--n-duration) var(--n-easing),
|
|
405
|
+
display var(--n-duration) var(--n-easing) allow-discrete,
|
|
406
|
+
overlay var(--n-duration) var(--n-easing) allow-discrete;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
:where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]):popover-open {
|
|
410
|
+
opacity: 1;
|
|
411
|
+
transform: none;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@starting-style {
|
|
415
|
+
:where(n-chat-message) > :where(n-toolbar[data-role="actions"][popover]):popover-open {
|
|
416
|
+
opacity: 0;
|
|
417
|
+
transform: perspective(800px) scale(0.96) rotateX(-20deg);
|
|
418
|
+
}
|
|
396
419
|
}
|
|
397
420
|
|
|
398
421
|
/* Override n-toolbar display to respect popover hidden state */
|
package/dist/native-chat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, c as t, d as n, f as r, g as i, h as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h } from "./chat-input-structured-element-
|
|
1
|
+
import { a as e, c as t, d as n, f as r, g as i, h as a, i as o, l as s, m as c, n as l, o as u, p as d, r as f, s as p, t as m, u as h } from "./chat-input-structured-element-DPKHlnRm.js";
|
|
2
2
|
/**
|
|
3
3
|
* Parse a Server-Sent Events (SSE) response stream into ChatStreamChunk values.
|
|
4
4
|
*
|
package/dist/register.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, d as t, g as n, h as r, i, l as a, m as o, n as s, p as c, r as l, t as u } from "./chat-input-structured-element-
|
|
1
|
+
import { a as e, d as t, g as n, h as r, i, l as a, m as o, n as s, p as c, r as l, t as u } from "./chat-input-structured-element-DPKHlnRm.js";
|
|
2
2
|
import { NButton as d, NCard as f, NDialog as p, NIcon as m, NTextarea as h, NToolbar as g, define as _, registerIcon as v } from "@nonoun/native-ui";
|
|
3
3
|
_("n-chat-input", n), _("native-chat-panel", r), _("n-chat-feed", o), _("n-chat-avatar", c), _("n-chat-message", t), _("n-chat-messages", a), _("n-chat-message-text", e), _("n-chat-message-activity", i), _("n-chat-message-seed", l), _("n-chat-message-genui", s), _("n-chat-input-structured", u), _("n-textarea", h), _("n-button", d), _("n-icon", m), _("n-toolbar", g), _("n-dialog", p), _("n-card", f), v("chat-dots", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M116,128a12,12,0,1,1,12,12A12,12,0,0,1,116,128ZM84,140a12,12,0,1,0-12-12A12,12,0,0,0,84,140Zm88,0a12,12,0,1,0-12-12A12,12,0,0,0,172,140Zm60-76V192a16,16,0,0,1-16,16H83l-32.6,28.16-.09.07A15.89,15.89,0,0,1,40,240a16.13,16.13,0,0,1-6.8-1.52A15.85,15.85,0,0,1,24,224V64A16,16,0,0,1,40,48H216A16,16,0,0,1,232,64ZM40,224h0ZM216,64H40V224l34.77-30A8,8,0,0,1,80,192H216Z\"/></svg>"), v("user", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M230.92,212c-15.23-26.33-38.7-45.21-66.09-54.16a72,72,0,1,0-73.66,0C63.78,166.78,40.31,185.66,25.08,212a8,8,0,1,0,13.85,8C55.71,194.74,89.05,176,128,176s72.29,18.74,89.07,44a8,8,0,0,0,13.85-8ZM72,96a56,56,0,1,1,56,56A56.06,56.06,0,0,1,72,96Z\"/></svg>"), v("stop", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M200,40H56A16,16,0,0,0,40,56V200a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Zm0,160H56V56H200V200Z\"/></svg>"), v("arrow-counter-clockwise", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M224,128a96,96,0,0,1-94.71,96H128A95.38,95.38,0,0,1,62.1,197.8a8,8,0,0,1,11-11.63A80,80,0,1,0,71.43,71.39a3.07,3.07,0,0,1-.26.25L44.59,96H72a8,8,0,0,1,0,16H24a8,8,0,0,1-8-8V56a8,8,0,0,1,16,0V85.8L60.25,60A96,96,0,0,1,224,128Z\"/></svg>"), v("copy", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\"/></svg>"), v("arrow-clockwise", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16H211.4L184.81,71.64l-.25-.24a80,80,0,1,0-1.67,114.78,8,8,0,0,1,11,11.63A95.44,95.44,0,0,1,128,224h-1.32A96,96,0,1,1,195.75,60L224,85.8V56a8,8,0,1,1,16,0Z\"/></svg>"), v("pencil-simple", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM92.69,208H48V163.31l88-88L180.69,120ZM192,108.68,147.31,64l24-24L216,84.68Z\"/></svg>"), v("thumbs-up", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M234,80.12A24,24,0,0,0,216,72H160V56a40,40,0,0,0-40-40,8,8,0,0,0-7.16,4.42L75.06,96H32a16,16,0,0,0-16,16v88a16,16,0,0,0,16,16H204a24,24,0,0,0,23.82-21l12-96A24,24,0,0,0,234,80.12ZM32,112H72v88H32ZM223.94,97l-12,96a8,8,0,0,1-7.94,7H88V105.89l36.71-73.43A24,24,0,0,1,144,56V80a8,8,0,0,0,8,8h64a8,8,0,0,1,7.94,9Z\"/></svg>"), v("thumbs-down", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M239.82,157l-12-96A24,24,0,0,0,204,40H32A16,16,0,0,0,16,56v88a16,16,0,0,0,16,16H75.06l37.78,75.58A8,8,0,0,0,120,240a40,40,0,0,0,40-40V184h56a24,24,0,0,0,23.82-27ZM72,144H32V56H72Zm150,21.29a7.88,7.88,0,0,1-6,2.71H152a8,8,0,0,0-8,8v24a24,24,0,0,1-19.29,23.54L88,150.11V56H204a8,8,0,0,1,7.94,7l12,96A7.87,7.87,0,0,1,222,165.29Z\"/></svg>"), v("arrow-right", "<svg viewBox=\"0 0 256 256\" fill=\"currentColor\"><path d=\"M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z\"/></svg>");
|
|
4
4
|
export { c as NChatAvatar, o as NChatFeed, n as NChatInput, u as NChatInputStructured, t as NChatMessage, i as NChatMessageActivity, s as NChatMessageGenUI, l as NChatMessageSeed, e as NChatMessageText, a as NChatMessages, r as NChatPanel };
|