@adecore/agents-react 0.37.1 → 0.37.3

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 (105) hide show
  1. package/dist/chat/chat-client.d.ts +1 -0
  2. package/dist/chat/chat-client.js +2 -1
  3. package/dist/chat/chat-references.d.ts +16 -1
  4. package/dist/chat/chat-references.js +29 -3
  5. package/dist/chat/drafts.d.ts +2 -0
  6. package/dist/chat/drafts.js +21 -5
  7. package/dist/chat/index.d.ts +1 -1
  8. package/dist/chat/logic/picker-entries.d.ts +6 -1
  9. package/dist/chat/logic/picker-entries.js +10 -0
  10. package/dist/chat/mentions.d.ts +31 -14
  11. package/dist/chat/mentions.js +186 -41
  12. package/dist/chat/stash.d.ts +1 -0
  13. package/dist/chat/stash.js +4 -2
  14. package/dist/chat/ui/Composer.js +438 -429
  15. package/dist/chat/ui/ComposerInput.d.ts +1 -0
  16. package/dist/chat/ui/ComposerInput.js +2 -0
  17. package/dist/chat/ui/Markdown.d.ts +3 -1
  18. package/dist/chat/ui/Markdown.js +194 -120
  19. package/dist/chat/ui/MessageActions.js +70 -66
  20. package/dist/chat/ui/Pickers.js +151 -207
  21. package/dist/chat/ui/ReferenceChip.d.ts +15 -0
  22. package/dist/chat/ui/ReferenceChip.js +255 -0
  23. package/dist/chat/ui/RunSettings.js +25 -21
  24. package/dist/chat/ui/Timeline.js +52 -29
  25. package/dist/chat/ui/TimelineMenu.js +84 -78
  26. package/dist/chat/ui/chip-clipboard.d.ts +9 -0
  27. package/dist/chat/ui/chip-clipboard.js +105 -0
  28. package/dist/chat/ui/chips.d.ts +5 -0
  29. package/dist/chat/ui/chips.js +15 -1
  30. package/dist/chat/ui/composer/ComposerMenu.js +140 -79
  31. package/dist/chat/ui/composer/DraftParts.d.ts +0 -4
  32. package/dist/chat/ui/composer/DraftParts.js +0 -41
  33. package/dist/chat/ui/composer/chip-paste.d.ts +15 -0
  34. package/dist/chat/ui/composer/chip-paste.js +104 -0
  35. package/dist/chat/ui/composer/chips.d.ts +5 -0
  36. package/dist/chat/ui/composer/chips.js +59 -9
  37. package/dist/chat/ui/composer/key-handler.js +9 -0
  38. package/dist/chat/ui/composer/use-composer-draft.d.ts +0 -1
  39. package/dist/chat/ui/composer/use-composer-draft.js +2 -10
  40. package/dist/chat/ui/composer/use-composer-menus.d.ts +12 -2
  41. package/dist/chat/ui/composer/use-composer-menus.js +192 -149
  42. package/dist/chat/ui/composer/use-composer-submit.js +17 -12
  43. package/dist/chat/ui/composer/use-draft-files.d.ts +7 -1
  44. package/dist/chat/ui/composer/use-draft-files.js +90 -58
  45. package/dist/chat/ui/composer/use-take-back.js +2 -1
  46. package/dist/chat/ui/index.d.ts +0 -1
  47. package/dist/chat/ui/index.js +0 -1
  48. package/dist/chat/ui/reference-icons.d.ts +3 -0
  49. package/dist/chat/ui/reference-icons.js +15 -0
  50. package/dist/chat/ui/reference-lookup.d.ts +7 -0
  51. package/dist/chat/ui/reference-lookup.js +6 -0
  52. package/dist/chat/ui/rehype-chips.d.ts +8 -1
  53. package/dist/chat/ui/rehype-chips.js +35 -11
  54. package/dist/chat/ui/rows/MessageRows.js +218 -158
  55. package/dist/chat/ui/thread-references.d.ts +4 -0
  56. package/dist/chat/ui/thread-references.js +78 -0
  57. package/dist/host-hooks.d.ts +2 -0
  58. package/dist/host-hooks.js +7 -0
  59. package/dist/host.d.ts +3 -0
  60. package/dist/locales/en/agent-chat.d.ts +20 -3
  61. package/dist/locales/en/agent-chat.js +24 -7
  62. package/dist/locales/nl/agent-chat.d.ts +20 -3
  63. package/dist/locales/nl/agent-chat.js +24 -7
  64. package/package.json +8 -8
  65. package/src/chat/chat-client.ts +4 -1
  66. package/src/chat/chat-references.ts +44 -3
  67. package/src/chat/drafts.ts +24 -6
  68. package/src/chat/index.ts +1 -1
  69. package/src/chat/logic/picker-entries.ts +12 -1
  70. package/src/chat/mentions.ts +202 -36
  71. package/src/chat/stash.ts +6 -2
  72. package/src/chat/ui/Composer.tsx +14 -4
  73. package/src/chat/ui/ComposerInput.tsx +4 -0
  74. package/src/chat/ui/Markdown.tsx +57 -25
  75. package/src/chat/ui/MessageActions.tsx +5 -2
  76. package/src/chat/ui/Pickers.tsx +8 -2
  77. package/src/chat/ui/ReferenceChip.tsx +74 -0
  78. package/src/chat/ui/RunSettings.tsx +29 -23
  79. package/src/chat/ui/Timeline.tsx +24 -2
  80. package/src/chat/ui/TimelineMenu.tsx +7 -3
  81. package/src/chat/ui/chip-clipboard.ts +115 -0
  82. package/src/chat/ui/chips.ts +20 -1
  83. package/src/chat/ui/composer/ComposerMenu.tsx +53 -37
  84. package/src/chat/ui/composer/DraftParts.tsx +0 -12
  85. package/src/chat/ui/composer/chip-paste.ts +122 -0
  86. package/src/chat/ui/composer/chips.ts +60 -10
  87. package/src/chat/ui/composer/key-handler.ts +9 -0
  88. package/src/chat/ui/composer/use-composer-draft.ts +1 -7
  89. package/src/chat/ui/composer/use-composer-menus.ts +68 -29
  90. package/src/chat/ui/composer/use-composer-submit.ts +13 -6
  91. package/src/chat/ui/composer/use-draft-files.ts +39 -5
  92. package/src/chat/ui/composer/use-take-back.ts +2 -1
  93. package/src/chat/ui/index.ts +0 -1
  94. package/src/chat/ui/reference-icons.ts +17 -0
  95. package/src/chat/ui/reference-lookup.ts +13 -0
  96. package/src/chat/ui/rehype-chips.ts +38 -13
  97. package/src/chat/ui/rows/MessageRows.tsx +88 -64
  98. package/src/chat/ui/thread-references.ts +47 -0
  99. package/src/host-hooks.ts +9 -0
  100. package/src/host.ts +6 -1
  101. package/src/locales/en/agent-chat.ts +24 -7
  102. package/src/locales/nl/agent-chat.ts +24 -7
  103. package/dist/chat/ui/ChatReferenceChip.d.ts +0 -4
  104. package/dist/chat/ui/ChatReferenceChip.js +0 -110
  105. package/src/chat/ui/ChatReferenceChip.tsx +0 -26
@@ -9,12 +9,14 @@ import { markdownOf, messageTextOf } from '../logic/timeline-copy.js';
9
9
  import { useChatHost } from '../../host.js';
10
10
  import { useChatScope } from '../../scope.js';
11
11
  import { useChatRow } from '../../state/chats.js';
12
+ import { copyWithChips, rowClipboardChips } from './chip-clipboard.js';
12
13
  import { useFileLinkCwd, useFileLinkScopeId, useOpenFileLink } from './file-links.js';
14
+ import { useReferenceLookup } from './thread-references.js';
13
15
  import { ContextMenu, copyText, DisabledReason, EDIT_SHORTCUTS, Icon, Kbd, selectAllWithin } from '@adecore/ui';
14
16
  /* The menu behind a right-click in a thread, mostly for copying: a whole message, a code block or an answer's markdown. */
15
17
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
16
18
  export function TimelineMenuPopup(t0) {
17
- const $ = _c(70);
19
+ const $ = _c(72);
18
20
  const {
19
21
  target,
20
22
  thread,
@@ -26,10 +28,11 @@ export function TimelineMenuPopup(t0) {
26
28
  const {
27
29
  t
28
30
  } = useTranslation("agent-chat");
31
+ const row = target.row;
29
32
  let t3;
30
- if ($[0] !== target.row) {
31
- t3 = target.row === null ? null : messageTextOf(target.row);
32
- $[0] = target.row;
33
+ if ($[0] !== row) {
34
+ t3 = row === null ? null : messageTextOf(row);
35
+ $[0] = row;
33
36
  $[1] = t3;
34
37
  } else {
35
38
  t3 = $[1];
@@ -47,7 +50,7 @@ export function TimelineMenuPopup(t0) {
47
50
  const turnId = t4;
48
51
  let t5;
49
52
  if ($[5] !== turnId) {
50
- t5 = row => turnId === null ? null : forkRefusal(row?.info ?? null, row?.structure[turnId]);
53
+ t5 = row_0 => turnId === null ? null : forkRefusal(row_0?.info ?? null, row_0?.structure[turnId]);
51
54
  $[5] = turnId;
52
55
  $[6] = t5;
53
56
  } else {
@@ -66,6 +69,7 @@ export function TimelineMenuPopup(t0) {
66
69
  const markable = chatId !== null && (target.row?.kind === "user" || target.row?.kind === "assistant") ? target.row.id : null;
67
70
  const cwd = useFileLinkCwd();
68
71
  const scopeId = useFileLinkScopeId();
72
+ const lookup = useReferenceLookup(chatId ?? "");
69
73
  const {
70
74
  fork,
71
75
  fileLinks
@@ -150,22 +154,24 @@ export function TimelineMenuPopup(t0) {
150
154
  t13 = $[25];
151
155
  }
152
156
  let t14;
153
- if ($[26] !== message || $[27] !== t) {
154
- t14 = message !== null && /*#__PURE__*/_jsxs(ContextMenu.Item, {
155
- onClick: () => copyText(message),
157
+ if ($[26] !== lookup || $[27] !== message || $[28] !== row || $[29] !== t) {
158
+ t14 = row !== null && message !== null && /*#__PURE__*/_jsxs(ContextMenu.Item, {
159
+ onClick: () => copyWithChips(rowClipboardChips(row, message, lookup)),
156
160
  children: [/*#__PURE__*/_jsx(Icon, {
157
161
  icon: MessageSquare,
158
162
  size: 14
159
163
  }), " ", t("timeline.menu.copyMessage")]
160
164
  });
161
- $[26] = message;
162
- $[27] = t;
163
- $[28] = t14;
165
+ $[26] = lookup;
166
+ $[27] = message;
167
+ $[28] = row;
168
+ $[29] = t;
169
+ $[30] = t14;
164
170
  } else {
165
- t14 = $[28];
171
+ t14 = $[30];
166
172
  }
167
173
  let t15;
168
- if ($[29] !== t || $[30] !== target.code) {
174
+ if ($[31] !== t || $[32] !== target.code) {
169
175
  t15 = target.code !== null && /*#__PURE__*/_jsxs(ContextMenu.Item, {
170
176
  onClick: () => copyText(target.code ?? ""),
171
177
  children: [/*#__PURE__*/_jsx(Icon, {
@@ -173,14 +179,14 @@ export function TimelineMenuPopup(t0) {
173
179
  size: 14
174
180
  }), " ", t("timeline.menu.copyCode")]
175
181
  });
176
- $[29] = t;
177
- $[30] = target.code;
178
- $[31] = t15;
182
+ $[31] = t;
183
+ $[32] = target.code;
184
+ $[33] = t15;
179
185
  } else {
180
- t15 = $[31];
186
+ t15 = $[33];
181
187
  }
182
188
  let t16;
183
- if ($[32] !== markdown || $[33] !== t) {
189
+ if ($[34] !== markdown || $[35] !== t) {
184
190
  t16 = markdown !== null && /*#__PURE__*/_jsxs(ContextMenu.Item, {
185
191
  onClick: () => copyText(markdown),
186
192
  children: [/*#__PURE__*/_jsx(Icon, {
@@ -188,14 +194,14 @@ export function TimelineMenuPopup(t0) {
188
194
  size: 14
189
195
  }), " ", t("timeline.menu.copyMarkdown")]
190
196
  });
191
- $[32] = markdown;
192
- $[33] = t;
193
- $[34] = t16;
197
+ $[34] = markdown;
198
+ $[35] = t;
199
+ $[36] = t16;
194
200
  } else {
195
- t16 = $[34];
201
+ t16 = $[36];
196
202
  }
197
203
  let t17;
198
- if ($[35] !== chatId || $[36] !== fork || $[37] !== forkBlocked || $[38] !== t || $[39] !== turnId) {
204
+ if ($[37] !== chatId || $[38] !== fork || $[39] !== forkBlocked || $[40] !== t || $[41] !== turnId) {
199
205
  t17 = chatId !== null && turnId !== null && fork !== null && /*#__PURE__*/_jsx(DisabledReason, {
200
206
  reason: forkBlocked,
201
207
  children: /*#__PURE__*/_jsxs(ContextMenu.Item, {
@@ -207,74 +213,74 @@ export function TimelineMenuPopup(t0) {
207
213
  }), " ", t("timeline.menu.forkFromHere")]
208
214
  })
209
215
  });
210
- $[35] = chatId;
211
- $[36] = fork;
212
- $[37] = forkBlocked;
213
- $[38] = t;
214
- $[39] = turnId;
215
- $[40] = t17;
216
+ $[37] = chatId;
217
+ $[38] = fork;
218
+ $[39] = forkBlocked;
219
+ $[40] = t;
220
+ $[41] = turnId;
221
+ $[42] = t17;
216
222
  } else {
217
- t17 = $[40];
223
+ t17 = $[42];
218
224
  }
219
225
  let t18;
220
- if ($[41] !== chatId || $[42] !== markable) {
226
+ if ($[43] !== chatId || $[44] !== markable) {
221
227
  t18 = chatId !== null && markable !== null && /*#__PURE__*/_jsx(BookmarkMenuItems, {
222
228
  chatId: chatId,
223
229
  itemId: markable
224
230
  });
225
- $[41] = chatId;
226
- $[42] = markable;
227
- $[43] = t18;
231
+ $[43] = chatId;
232
+ $[44] = markable;
233
+ $[45] = t18;
228
234
  } else {
229
- t18 = $[43];
235
+ t18 = $[45];
230
236
  }
231
237
  let t19;
232
- if ($[44] === Symbol.for("react.memo_cache_sentinel")) {
238
+ if ($[46] === Symbol.for("react.memo_cache_sentinel")) {
233
239
  t19 = /*#__PURE__*/_jsx(ContextMenu.Separator, {});
234
- $[44] = t19;
240
+ $[46] = t19;
235
241
  } else {
236
- t19 = $[44];
242
+ t19 = $[46];
237
243
  }
238
244
  let t20;
239
- if ($[45] !== thread.current) {
245
+ if ($[47] !== thread.current) {
240
246
  t20 = () => selectAllWithin(thread.current);
241
- $[45] = thread.current;
242
- $[46] = t20;
247
+ $[47] = thread.current;
248
+ $[48] = t20;
243
249
  } else {
244
- t20 = $[46];
250
+ t20 = $[48];
245
251
  }
246
252
  let t21;
247
- if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
253
+ if ($[49] === Symbol.for("react.memo_cache_sentinel")) {
248
254
  t21 = /*#__PURE__*/_jsx(Icon, {
249
255
  icon: Scan,
250
256
  size: 14
251
257
  });
252
- $[47] = t21;
258
+ $[49] = t21;
253
259
  } else {
254
- t21 = $[47];
260
+ t21 = $[49];
255
261
  }
256
262
  let t22;
257
- if ($[48] !== t) {
263
+ if ($[50] !== t) {
258
264
  t22 = t("common.action.selectAll");
259
- $[48] = t;
260
- $[49] = t22;
265
+ $[50] = t;
266
+ $[51] = t22;
261
267
  } else {
262
- t22 = $[49];
268
+ t22 = $[51];
263
269
  }
264
270
  let t23;
265
- if ($[50] !== t20 || $[51] !== t22) {
271
+ if ($[52] !== t20 || $[53] !== t22) {
266
272
  t23 = /*#__PURE__*/_jsxs(ContextMenu.Item, {
267
273
  onClick: t20,
268
274
  children: [t21, " ", t22]
269
275
  });
270
- $[50] = t20;
271
- $[51] = t22;
272
- $[52] = t23;
276
+ $[52] = t20;
277
+ $[53] = t22;
278
+ $[54] = t23;
273
279
  } else {
274
- t23 = $[52];
280
+ t23 = $[54];
275
281
  }
276
282
  let t24;
277
- if ($[53] !== fileLinks || $[54] !== openInPreview || $[55] !== t || $[56] !== target.path) {
283
+ if ($[55] !== fileLinks || $[56] !== openInPreview || $[57] !== t || $[58] !== target.path) {
278
284
  t24 = target.path !== null && fileLinks !== null && /*#__PURE__*/_jsxs(_Fragment, {
279
285
  children: [/*#__PURE__*/_jsx(ContextMenu.Separator, {}), /*#__PURE__*/_jsxs(ContextMenu.Item, {
280
286
  onClick: openInPreview,
@@ -284,41 +290,41 @@ export function TimelineMenuPopup(t0) {
284
290
  }), " ", t("timeline.menu.openInPreview")]
285
291
  })]
286
292
  });
287
- $[53] = fileLinks;
288
- $[54] = openInPreview;
289
- $[55] = t;
290
- $[56] = target.path;
291
- $[57] = t24;
293
+ $[55] = fileLinks;
294
+ $[56] = openInPreview;
295
+ $[57] = t;
296
+ $[58] = target.path;
297
+ $[59] = t24;
292
298
  } else {
293
- t24 = $[57];
299
+ t24 = $[59];
294
300
  }
295
301
  let t25;
296
- if ($[58] !== column) {
302
+ if ($[60] !== column) {
297
303
  t25 = column && /*#__PURE__*/_jsxs(_Fragment, {
298
304
  children: [/*#__PURE__*/_jsx(ContextMenu.Separator, {}), /*#__PURE__*/_jsx(ReadingWidthSubmenu, {})]
299
305
  });
300
- $[58] = column;
301
- $[59] = t25;
306
+ $[60] = column;
307
+ $[61] = t25;
302
308
  } else {
303
- t25 = $[59];
309
+ t25 = $[61];
304
310
  }
305
311
  let t26;
306
- if ($[60] !== t13 || $[61] !== t14 || $[62] !== t15 || $[63] !== t16 || $[64] !== t17 || $[65] !== t18 || $[66] !== t23 || $[67] !== t24 || $[68] !== t25) {
312
+ if ($[62] !== t13 || $[63] !== t14 || $[64] !== t15 || $[65] !== t16 || $[66] !== t17 || $[67] !== t18 || $[68] !== t23 || $[69] !== t24 || $[70] !== t25) {
307
313
  t26 = /*#__PURE__*/_jsxs(ContextMenu.Popup, {
308
314
  children: [t13, t14, t15, t16, t17, t18, t19, t23, t24, t25]
309
315
  });
310
- $[60] = t13;
311
- $[61] = t14;
312
- $[62] = t15;
313
- $[63] = t16;
314
- $[64] = t17;
315
- $[65] = t18;
316
- $[66] = t23;
317
- $[67] = t24;
318
- $[68] = t25;
319
- $[69] = t26;
320
- } else {
321
- t26 = $[69];
316
+ $[62] = t13;
317
+ $[63] = t14;
318
+ $[64] = t15;
319
+ $[65] = t16;
320
+ $[66] = t17;
321
+ $[67] = t18;
322
+ $[68] = t23;
323
+ $[69] = t24;
324
+ $[70] = t25;
325
+ $[71] = t26;
326
+ } else {
327
+ t26 = $[71];
322
328
  }
323
329
  return t26;
324
330
  }
@@ -0,0 +1,9 @@
1
+ import type { ChatAssistantItem, ChatUserItem } from '@adecore/agent-contracts';
2
+ import { type ClipboardChips } from '../mentions.js';
3
+ import type { TimelineRow } from '../logic/timeline.js';
4
+ import type { ReferenceLookup } from './reference-lookup.js';
5
+ export declare function messageClipboardChips(item: ChatUserItem | ChatAssistantItem, text: string, lookup: Pick<ReferenceLookup, 'items' | 'referenced'>): ClipboardChips;
6
+ export declare function rowClipboardChips(row: TimelineRow, text: string, lookup: Pick<ReferenceLookup, 'items' | 'referenced'>): ClipboardChips;
7
+ export declare function selectionChips(selection: Selection): ClipboardChips;
8
+ export declare function copySelectionWithChips(event: ClipboardEvent): void;
9
+ export declare function copyWithChips(chips: ClipboardChips): void;
@@ -0,0 +1,105 @@
1
+ import { copyText } from '@adecore/ui';
2
+ import { referenceTokens } from '../chat-references.js';
3
+ import { clipboardChipsOf, hasClipboardChips, tokenizeChips, tokenizeNamedReferences, writeClipboardChips } from '../mentions.js';
4
+ /* The chips a copy of a whole message carries: what the person picked, or what a reply names. */
5
+ export function messageClipboardChips(item, text, lookup) {
6
+ if (item.kind === 'assistant') {
7
+ return clipboardChipsOf(text, tokenizeNamedReferences(text, lookup.items, lookup.referenced));
8
+ }
9
+ const tokens = referenceTokens([...(item.chats ?? []), ...(item.references ?? [])], lookup.items);
10
+ return clipboardChipsOf(text, tokenizeChips(text, item.mentions ?? [], item.skills ?? [], tokens));
11
+ }
12
+ /* The chips a copy of a row of the thread carries; only a message has any. */
13
+ export function rowClipboardChips(row, text, lookup) {
14
+ if (row.kind === 'user' || row.kind === 'assistant') {
15
+ return messageClipboardChips(row.item, text, lookup);
16
+ }
17
+ return clipboardChipsOf(text, []);
18
+ }
19
+ /* What a chip the transcript drew stands for, read back from the attributes `TokenChip` writes. */
20
+ function segmentOf(chip) {
21
+ const value = chip.getAttribute('data-chip-value');
22
+ if (value === null) {
23
+ return null;
24
+ }
25
+ switch (chip.getAttribute('data-chip')) {
26
+ case 'mention':
27
+ return {
28
+ kind: 'mention',
29
+ path: value
30
+ };
31
+ case 'skill':
32
+ return {
33
+ kind: 'skill',
34
+ name: value
35
+ };
36
+ case 'reference':
37
+ {
38
+ const name = chip.getAttribute('data-chip-name');
39
+ return name === null || name === '' ? null : {
40
+ kind: 'reference',
41
+ id: value,
42
+ name
43
+ };
44
+ }
45
+ default:
46
+ return null;
47
+ }
48
+ }
49
+ /* The chips a selection holds whole, beside the text it copies; a chip cut in half is only text. */
50
+ export function selectionChips(selection) {
51
+ const segments = [];
52
+ for (let i = 0; i < selection.rangeCount; i++) {
53
+ const container = selection.getRangeAt(i).commonAncestorContainer;
54
+ const root = container instanceof Element ? container : container.parentElement;
55
+ const own = root?.closest('[data-chip]');
56
+ const candidates = own ? [own] : [...(root?.querySelectorAll('[data-chip]') ?? [])];
57
+ for (const chip of candidates) {
58
+ const segment = selection.containsNode(chip, false) ? segmentOf(chip) : null;
59
+ if (segment !== null) {
60
+ segments.push(segment);
61
+ }
62
+ }
63
+ }
64
+ return clipboardChipsOf(selection.toString(), segments);
65
+ }
66
+ /* A copy of a selection in the thread, which carries the chips in it as well when it holds any. */
67
+ export function copySelectionWithChips(event) {
68
+ const selection = document.getSelection();
69
+ if (event.defaultPrevented || event.clipboardData === null || selection === null || selection.isCollapsed) {
70
+ return;
71
+ }
72
+ const chips = selectionChips(selection);
73
+ if (!hasClipboardChips(chips)) {
74
+ return;
75
+ }
76
+ writeClipboardChips(event.clipboardData, chips);
77
+ event.preventDefault();
78
+ }
79
+ /*
80
+ * Copies a text and its chips. The asynchronous clipboard writes no type of an app's own that a paste
81
+ * can read, so the copy goes through a copy event, which only a page with the user's gesture gets.
82
+ */
83
+ export function copyWithChips(chips) {
84
+ if (!hasClipboardChips(chips) || typeof document.execCommand !== 'function') {
85
+ void copyText(chips.text);
86
+ return;
87
+ }
88
+ let written = false;
89
+ const write = event => {
90
+ if (event.clipboardData !== null) {
91
+ writeClipboardChips(event.clipboardData, chips);
92
+ event.preventDefault();
93
+ written = true;
94
+ }
95
+ };
96
+ document.addEventListener('copy', write, true);
97
+ try {
98
+ document.execCommand('copy');
99
+ } finally {
100
+ document.removeEventListener('copy', write, true);
101
+ }
102
+ if (!written) {
103
+ void copyText(chips.text);
104
+ }
105
+ }
@@ -1,4 +1,9 @@
1
1
  export declare const MENTION_TONE = "bg-accent-soft text-accent shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--accent)_25%,transparent)]";
2
2
  export declare const SKILL_TONE = "bg-skill-soft text-skill shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--skill)_25%,transparent)]";
3
+ export declare const REFERENCE_TONE = "bg-text/8 text-text shadow-[inset_0_0_0_1px_var(--border-strong)]";
4
+ export declare const REFERENCE_GONE_TONE = "bg-text/4 text-text-faint shadow-[inset_0_0_0_1px_var(--border)]";
3
5
  export declare const CHIP_IN_EDITOR = "box-decoration-clone rounded-md px-1 py-0.5";
6
+ export declare const TOKEN_IN_MESSAGE = "box-decoration-clone rounded-md px-1.5 py-0.5 text-xs font-medium";
7
+ export declare const TOKEN_ICON = "mr-1 inline align-[calc(0.5cap-7px)]!";
8
+ export declare const TOKEN_ICON_IN_EDITOR = "mr-1 inline-block align-[calc(0.5cap-6px)]";
4
9
  export declare const CHIP_IN_MESSAGE = "inline-flex h-5 max-w-full items-center gap-1 rounded-md px-1.5 align-[-3px] text-xs/none font-medium";
@@ -1,11 +1,25 @@
1
- /* An `@file` or `$skill` token drawn as a pill: the tone says which of the two it is, the shape
1
+ /* An `@file`, `$skill` or `#reference` token drawn as a pill: the tone says which it is, the shape
2
2
  says where it is drawn. */
3
3
  export const MENTION_TONE = 'bg-accent-soft text-accent shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--accent)_25%,transparent)]';
4
4
  /* A skill is the same token shape as a file mention, in its own hue. */
5
5
  export const SKILL_TONE = 'bg-skill-soft text-skill shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--skill)_25%,transparent)]';
6
+ /* A `#` to a view, node or chat is neutral, so it never reads as a file or a skill. */
7
+ export const REFERENCE_TONE = 'bg-text/8 text-text shadow-[inset_0_0_0_1px_var(--border-strong)]';
8
+ /* A `#` whose view or node is no longer in the project. */
9
+ export const REFERENCE_GONE_TONE = 'bg-text/4 text-text-faint shadow-[inset_0_0_0_1px_var(--border)]';
6
10
  /* The pill in the composer's editor, around the token's own characters: the editor places the caret
7
11
  from what it drew, so padding is safe, and a chip that wraps keeps it on every fragment. */
8
12
  export const CHIP_IN_EDITOR = 'box-decoration-clone rounded-md px-1 py-0.5';
13
+ /* A picked or named token in a message or a reply, a shade smaller than the text around it. Inline like
14
+ the editor's pill, so its name sits on the baseline of the sentence, and a selection copies it on the
15
+ same line as the words around it, where a flex box would put it on lines of its own. */
16
+ export const TOKEN_IN_MESSAGE = 'box-decoration-clone rounded-md px-1.5 py-0.5 text-xs font-medium';
17
+ /* The mark in place of the sigil, a 14px icon. Inline, since the base styles make an svg a block of its
18
+ own. Its middle goes on the middle of the name's capitals, where a mark reads as centered; the middle
19
+ of the x-height `Icon` aligns on sits low next to a capital. */
20
+ export const TOKEN_ICON = 'mr-1 inline align-[calc(0.5cap-7px)]!';
21
+ /* The same middle for the 12px mark the composer draws, in a box whose bottom edge is its baseline. */
22
+ export const TOKEN_ICON_IN_EDITOR = 'mr-1 inline-block align-[calc(0.5cap-6px)]';
9
23
  /* The same pill in the transcript: a real inline box a shade smaller than the text around it, with
10
24
  the icon in place of the sigil. */
11
25
  export const CHIP_IN_MESSAGE = 'inline-flex h-5 max-w-full items-center gap-1 rounded-md px-1.5 align-[-3px] text-xs/none font-medium';