@k2b/ui 0.32.0 → 0.33.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.
Files changed (109) hide show
  1. package/dist/browser/actions/Dropdown.js +159 -99
  2. package/dist/browser/actions/Dropdown.js.map +1 -1
  3. package/dist/browser/actions/FilterChip.js +113 -56
  4. package/dist/browser/actions/FilterChip.js.map +1 -1
  5. package/dist/browser/actions/filter-messages.js +26 -2
  6. package/dist/browser/actions/filter-messages.js.map +1 -1
  7. package/dist/browser/actions/menu-rows.js +23 -3
  8. package/dist/browser/actions/menu-rows.js.map +1 -1
  9. package/dist/browser/actions/menu-sheet.js +2 -7
  10. package/dist/browser/actions/menu-sheet.js.map +1 -1
  11. package/dist/browser/chat/ChatComposer.js +480 -403
  12. package/dist/browser/chat/ChatComposer.js.map +1 -1
  13. package/dist/browser/chat/chat-messages.js +14 -0
  14. package/dist/browser/chat/chat-messages.js.map +1 -1
  15. package/dist/browser/chat/index.js.map +1 -1
  16. package/dist/browser/content/Calendar.js +39 -29
  17. package/dist/browser/content/Calendar.js.map +1 -1
  18. package/dist/browser/content/CalendarDayView.js +159 -165
  19. package/dist/browser/content/CalendarDayView.js.map +1 -1
  20. package/dist/browser/content/MessageRow.js +607 -343
  21. package/dist/browser/content/MessageRow.js.map +1 -1
  22. package/dist/browser/content/ReactionBar.js +17 -0
  23. package/dist/browser/content/ReactionBar.js.map +1 -1
  24. package/dist/browser/content/index.js +1 -1
  25. package/dist/browser/content/index.js.map +1 -1
  26. package/dist/browser/feedback/dialog-core.js +6 -0
  27. package/dist/browser/feedback/dialog-core.js.map +1 -1
  28. package/dist/browser/inputs/TextInput.js +4 -1
  29. package/dist/browser/inputs/TextInput.js.map +1 -1
  30. package/dist/browser/intl/shortcut-messages.js +4 -0
  31. package/dist/browser/intl/shortcut-messages.js.map +1 -1
  32. package/dist/browser/intl/shortcut.js +4 -0
  33. package/dist/browser/intl/shortcut.js.map +1 -1
  34. package/dist/browser/layout/AppWorkspace.js +529 -512
  35. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  36. package/dist/browser/layout/MobileShell.js +213 -38
  37. package/dist/browser/layout/MobileShell.js.map +1 -1
  38. package/dist/browser/layout/index.js +1 -0
  39. package/dist/browser/layout/index.js.map +1 -1
  40. package/dist/browser/layout/scroll-fade.js +32 -5
  41. package/dist/browser/layout/scroll-fade.js.map +1 -1
  42. package/dist/browser/surfaces/NoticeCard.js +46 -30
  43. package/dist/browser/surfaces/NoticeCard.js.map +1 -1
  44. package/dist/browser/surfaces/resource-messages.js +2 -2
  45. package/dist/browser/surfaces/resource-messages.js.map +1 -1
  46. package/dist/ssr/actions/Dropdown.js +51 -27
  47. package/dist/ssr/actions/Dropdown.js.map +1 -1
  48. package/dist/ssr/actions/FilterChip.js +67 -16
  49. package/dist/ssr/actions/FilterChip.js.map +1 -1
  50. package/dist/ssr/actions/filter-messages.js +26 -2
  51. package/dist/ssr/actions/filter-messages.js.map +1 -1
  52. package/dist/ssr/actions/menu-rows.js +23 -3
  53. package/dist/ssr/actions/menu-rows.js.map +1 -1
  54. package/dist/ssr/actions/menu-sheet.js +2 -7
  55. package/dist/ssr/actions/menu-sheet.js.map +1 -1
  56. package/dist/ssr/chat/ChatComposer.js +96 -67
  57. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  58. package/dist/ssr/chat/chat-messages.js +14 -0
  59. package/dist/ssr/chat/chat-messages.js.map +1 -1
  60. package/dist/ssr/chat/index.js.map +1 -1
  61. package/dist/ssr/content/Calendar.js +40 -31
  62. package/dist/ssr/content/Calendar.js.map +1 -1
  63. package/dist/ssr/content/CalendarDayView.js +40 -48
  64. package/dist/ssr/content/CalendarDayView.js.map +1 -1
  65. package/dist/ssr/content/MessageRow.js +264 -91
  66. package/dist/ssr/content/MessageRow.js.map +1 -1
  67. package/dist/ssr/content/ReactionBar.js +17 -0
  68. package/dist/ssr/content/ReactionBar.js.map +1 -1
  69. package/dist/ssr/content/index.js +1 -1
  70. package/dist/ssr/content/index.js.map +1 -1
  71. package/dist/ssr/feedback/dialog-core.js +6 -0
  72. package/dist/ssr/feedback/dialog-core.js.map +1 -1
  73. package/dist/ssr/inputs/TextInput.js +4 -1
  74. package/dist/ssr/inputs/TextInput.js.map +1 -1
  75. package/dist/ssr/intl/shortcut-messages.js +4 -0
  76. package/dist/ssr/intl/shortcut-messages.js.map +1 -1
  77. package/dist/ssr/intl/shortcut.js +4 -0
  78. package/dist/ssr/intl/shortcut.js.map +1 -1
  79. package/dist/ssr/layout/AppWorkspace.js +134 -122
  80. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  81. package/dist/ssr/layout/MobileShell.js +100 -20
  82. package/dist/ssr/layout/MobileShell.js.map +1 -1
  83. package/dist/ssr/layout/index.js +1 -0
  84. package/dist/ssr/layout/index.js.map +1 -1
  85. package/dist/ssr/layout/scroll-fade.js +32 -5
  86. package/dist/ssr/layout/scroll-fade.js.map +1 -1
  87. package/dist/ssr/surfaces/NoticeCard.js +21 -12
  88. package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
  89. package/dist/ssr/surfaces/resource-messages.js +2 -2
  90. package/dist/ssr/surfaces/resource-messages.js.map +1 -1
  91. package/dist/styles.css +1 -1
  92. package/dist/types/actions/Dropdown.d.ts +14 -0
  93. package/dist/types/actions/FilterChip.d.ts +11 -0
  94. package/dist/types/actions/filter-messages.d.ts +12 -0
  95. package/dist/types/actions/menu-rows.d.ts +7 -2
  96. package/dist/types/chat/ChatComposer.d.ts +13 -0
  97. package/dist/types/chat/chat-messages.d.ts +7 -0
  98. package/dist/types/chat/index.d.ts +1 -1
  99. package/dist/types/content/Calendar.d.ts +7 -0
  100. package/dist/types/content/MessageRow.d.ts +64 -2
  101. package/dist/types/content/index.d.ts +2 -2
  102. package/dist/types/feedback/dialog-core.d.ts +3 -0
  103. package/dist/types/intl/shortcut-messages.d.ts +2 -0
  104. package/dist/types/layout/AppWorkspace.d.ts +2 -0
  105. package/dist/types/layout/MobileShell.d.ts +52 -5
  106. package/dist/types/layout/index.d.ts +2 -1
  107. package/dist/types/layout/scroll-fade.d.ts +5 -0
  108. package/dist/types/surfaces/NoticeCard.d.ts +3 -0
  109. package/package.json +2 -2
@@ -8,35 +8,35 @@ var _tmpl$ = ["<span", " style=\"", "\">", "</span>"],
8
8
  _tmpl$2 = ["<span", " style=\"", "\" role=\"img\"", ">", "</span>"],
9
9
  _tmpl$3 = ["<a", " style=\"", "\"", " target=\"_blank\" rel=\"noopener noreferrer\"", ">", "</a>"],
10
10
  _tmpl$4 = ["<button type=\"button\"", " style=\"", "\"", ">", "</button>"],
11
- _tmpl$5 = ["<span class=\"k2b-message-row__name\">", "</span>"],
12
- _tmpl$6 = ["<span class=\"k2b-message-row__badge\">", "</span>"],
13
- _tmpl$7 = ["<time class=\"k2b-message-row__time\"", ">", "</time>"],
14
- _tmpl$8 = "<i class=\"ti ti-arrow-back-up\" aria-hidden=\"true\"></i>",
15
- _tmpl$9 = ["<span class=\"k2b-message-row__quote-text\"><span class=\"k2b-sr-only\">", " </span><span class=\"k2b-message-row__quote-author\">", "</span> ", "</span>"],
16
- _tmpl$0 = ["<img", " alt", " loading=\"lazy\" decoding=\"async\">"],
17
- _tmpl$1 = "<span class=\"k2b-message-row__media-play\" aria-hidden=\"true\"><i class=\"ti ti-player-play\"></i></span>",
18
- _tmpl$10 = ["<span class=\"k2b-message-row__media-duration\" aria-hidden=\"true\">", "</span>"],
19
- _tmpl$11 = ["<span class=\"k2b-message-row__media-more\" aria-hidden=\"true\">+", "</span>"],
20
- _tmpl$12 = ["<span class=\"k2b-message-row__avatar\" aria-hidden=\"true\">", "</span>"],
21
- _tmpl$13 = ["<div class=\"k2b-message-row__gutter\">", "</div>"],
22
- _tmpl$14 = ["<div class=\"k2b-message-row__meta\">", "</div>"],
23
- _tmpl$15 = ["<div class=\"k2b-message-row__marker\"><i class=\"ti ti-arrow-forward-up\" aria-hidden=\"true\"></i><span>", "</span></div>"],
24
- _tmpl$16 = ["<div", " class=\"k2b-content-markdown k2b-message-row__text\" data-heading-scale=\"compact\"", ">", "</div>"],
25
- _tmpl$17 = ["<span class=\"k2b-message-row__edited\">", "</span>"],
26
- _tmpl$18 = ["<div class=\"k2b-message-row__more-line\">", "", "</div>"],
27
- _tmpl$19 = ["<div class=\"k2b-message-row__bubble\"", ">", "</div>"],
28
- _tmpl$20 = ["<div class=\"k2b-message-row__marker\"><i class=\"ti ti-pencil\" aria-hidden=\"true\"></i><span class=\"k2b-message-row__edited\">", "</span></div>"],
29
- _tmpl$21 = ["<div class=\"k2b-message-row__media\" role=\"group\"", " style=\"", "\">", "</div>"],
30
- _tmpl$22 = ["<div class=\"k2b-message-row__files\">", "</div>"],
31
- _tmpl$23 = ["<div class=\"k2b-message-row__slot\" data-gesture-ignore>", "</div>"],
32
- _tmpl$24 = ["<div class=\"k2b-message-row__line\">", "</div>"],
33
- _tmpl$25 = ["<div class=\"k2b-message-row__footer\">", "", "</div>"],
34
- _tmpl$26 = ["<div class=\"k2b-message-row__actions\" role=\"group\"", ">", "</div>"],
35
- _tmpl$27 = ["<div", ">", "<div class=\"k2b-message-row__body\">", "", "", "", "", "", "", "", "", "", "", "</div>", "</div>"],
36
- _tmpl$28 = ["<span class=\"k2b-sr-only\">", ", ", ": </span>"],
37
- _tmpl$29 = ["<div class=\"k2b-message-row__meta\"><span class=\"k2b-sr-only\">", ", </span><time class=\"k2b-message-row__time\"", ">", "</time></div>"],
38
- _tmpl$30 = ["<div class=\"k2b-message-row__quote\">", "</div>"],
39
- _tmpl$31 = ["<button type=\"button\" class=\"k2b-message-row__quote\">", "</button>"],
11
+ _tmpl$5 = "<i class=\"ti ti-dots\" aria-hidden=\"true\"></i>",
12
+ _tmpl$6 = ["<span class=\"k2b-message-row__name\">", "</span>"],
13
+ _tmpl$7 = ["<span class=\"k2b-message-row__badge\">", "</span>"],
14
+ _tmpl$8 = ["<time class=\"k2b-message-row__time\"", ">", "</time>"],
15
+ _tmpl$9 = ["<span class=\"k2b-message-row__quote-author\"><span class=\"k2b-sr-only\">", " </span>", "</span>"],
16
+ _tmpl$0 = ["<span class=\"k2b-message-row__quote-text\">", "</span>"],
17
+ _tmpl$1 = ["<div class=\"k2b-message-row__quote\">", "</div>"],
18
+ _tmpl$10 = ["<button type=\"button\" class=\"k2b-message-row__quote\">", "</button>"],
19
+ _tmpl$11 = ["<img", " alt", " loading=\"lazy\" decoding=\"async\">"],
20
+ _tmpl$12 = "<span class=\"k2b-message-row__media-play\" aria-hidden=\"true\"><i class=\"ti ti-player-play\"></i></span>",
21
+ _tmpl$13 = ["<span class=\"k2b-message-row__media-duration\" aria-hidden=\"true\">", "</span>"],
22
+ _tmpl$14 = ["<span class=\"k2b-message-row__media-more\" aria-hidden=\"true\">+", "</span>"],
23
+ _tmpl$15 = ["<span class=\"k2b-message-row__avatar\" aria-hidden=\"true\">", "</span>"],
24
+ _tmpl$16 = ["<div class=\"k2b-message-row__gutter\">", "</div>"],
25
+ _tmpl$17 = ["<div class=\"k2b-message-row__meta\">", "</div>"],
26
+ _tmpl$18 = ["<div class=\"k2b-message-row__marker\"><i class=\"ti ti-arrow-forward-up\" aria-hidden=\"true\"></i><span>", "</span></div>"],
27
+ _tmpl$19 = ["<div", " class=\"k2b-content-markdown k2b-message-row__text\" data-heading-scale=\"compact\"", ">", "</div>"],
28
+ _tmpl$20 = ["<span class=\"k2b-message-row__edited\">", "</span>"],
29
+ _tmpl$21 = ["<div class=\"k2b-message-row__more-line\">", "", "</div>"],
30
+ _tmpl$22 = ["<div class=\"k2b-message-row__bubble\"", ">", "", "", "</div>"],
31
+ _tmpl$23 = ["<div class=\"k2b-message-row__marker\"><i class=\"ti ti-pencil\" aria-hidden=\"true\"></i><span class=\"k2b-message-row__edited\">", "</span></div>"],
32
+ _tmpl$24 = ["<div class=\"k2b-message-row__media\" role=\"group\"", " style=\"", "\">", "</div>"],
33
+ _tmpl$25 = ["<div class=\"k2b-message-row__files\">", "</div>"],
34
+ _tmpl$26 = ["<div class=\"k2b-message-row__slot\" data-gesture-ignore>", "</div>"],
35
+ _tmpl$27 = ["<div class=\"k2b-message-row__line\">", "</div>"],
36
+ _tmpl$28 = ["<div class=\"k2b-message-row__footer\">", "", "</div>"],
37
+ _tmpl$29 = ["<div", ">", "<div class=\"k2b-message-row__body\">", "", "", "", "", "", "", "", "", "", "", "", "", "</div></div>"],
38
+ _tmpl$30 = ["<span class=\"k2b-sr-only\">", ", ", ": </span>"],
39
+ _tmpl$31 = ["<div class=\"k2b-message-row__meta\"><span class=\"k2b-sr-only\">", ", </span><time class=\"k2b-message-row__time\"", ">", "</time></div>"],
40
40
  _tmpl$32 = ["<span class=\"k2b-message-row__deleted\"><i class=\"ti ti-message-off\" aria-hidden=\"true\"></i>", "</span>"],
41
41
  _tmpl$33 = "<span class=\"k2b-message-row__writing\"><span class=\"k2b-chat-progress-dots\" aria-hidden=\"true\"><span></span><span></span><span></span></span></span>",
42
42
  _tmpl$34 = ["<span class=\"k2b-message-row__file-icon\" aria-hidden=\"true\"><i", "></i></span>"],
@@ -54,18 +54,25 @@ var _tmpl$ = ["<span", " style=\"", "\">", "</span>"],
54
54
  _tmpl$46 = ["<span class=\"k2b-message-row__receipt\">", "</span>"],
55
55
  _tmpl$47 = "<i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\"></i>",
56
56
  _tmpl$48 = ["<span class=\"k2b-message-row__line-text\">", "</span>"],
57
- _tmpl$49 = ["<i", " aria-hidden=\"true\"></i>"],
58
- _tmpl$50 = ["<time", ">", "</time>"],
59
- _tmpl$51 = ["<div", ">", "<span>", "</span>", "</div>"];
57
+ _tmpl$49 = ["<span class=\"k2b-message-row__origin\">", "", "</span>"],
58
+ _tmpl$50 = ["<i", " aria-hidden=\"true\"></i>"],
59
+ _tmpl$51 = ["<button type=\"button\" class=\"k2b-message-row__origin\"", ">", "", "</button>"],
60
+ _tmpl$52 = ["<time", ">", "</time>"],
61
+ _tmpl$53 = ["<div", "><i", " aria-hidden=\"true\"></i><span class=\"k2b-message-event-row__text\">", "</span>", "", "</div>"],
62
+ _tmpl$54 = ["<button type=\"button\"", "><i class=\"ti ti-history\" aria-hidden=\"true\"></i><span class=\"k2b-message-event-row__text\">", "</span>", "<i", " aria-hidden=\"true\"></i></button>"],
63
+ _tmpl$55 = ["<div", ">", "<span>", "</span>", "</div>"];
60
64
  import { fileIcons } from "@k2b/stdlib";
61
65
  import { createMemo, createSignal, createUniqueId, For, onCleanup, Show } from "solid-js";
62
- import { Button, IconButton } from "../actions/Button";
66
+ import { Button } from "../actions/Button";
63
67
  import { copyText } from "../actions/CopyButton";
68
+ import { Dropdown } from "../actions/Dropdown";
69
+ import { GestureMenu } from "../actions/GestureMenu";
64
70
  import { useChatMessages } from "../chat/chat-messages";
65
71
  import { announce } from "../feedback/announce";
66
72
  import { useLocale } from "../intl/locale";
67
73
  import { useUiMessages } from "../intl/messages";
68
74
  import { Avatar } from "../surfaces/Avatar";
75
+ import { Kbd } from "./Kbd";
69
76
  import { createSafeMarked, createSafeRenderer, escapeHtml } from "./MarkdownView";
70
77
  import { ReactionBar } from "./ReactionBar";
71
78
 
@@ -82,6 +89,8 @@ const LINE_CHARS = 100;
82
89
  /** Lines at the bottom of a collapsed message that fade out, as `.k2b-message-row__text[data-collapsed]` draws them. */
83
90
  const FADE_LINES = 2;
84
91
  const COPIED_MS = 2_000;
92
+ /** Alt+click on these keeps its own meaning, such as downloading a link. */
93
+ const ALT_CLICK_IGNORE = "a[href], button, input, textarea, select, summary, label, audio, video, [role='button'], [role='link']";
85
94
  /** Links in messages may only use these schemes; other links show as their text. */
86
95
  const LINK_PROTOCOLS = ["https:", "http:", "mailto:"];
87
96
  /** Attachments open and load only from these schemes or from a relative URL. */
@@ -99,6 +108,8 @@ const MEDIA_RATIO_MAX = 3;
99
108
 
100
109
  /** Reaction labels are read by screen readers and shown in the names hint. */
101
110
 
111
+ /** Where a message belongs, shown as a small chip under it, for example its thread in a timeline of several. */
112
+
102
113
  const timestamp = value => value instanceof Date ? value.getTime() : new Date(value).getTime();
103
114
 
104
115
  /**
@@ -323,15 +334,91 @@ export function MessageRow(props) {
323
334
  const fade = text.getBoundingClientRect().bottom - FADE_LINES * Number.parseFloat(getComputedStyle(text).lineHeight);
324
335
  if (event.target.getBoundingClientRect().bottom > fade) setExpanded(true);
325
336
  };
326
- const header = () => [_$ssr(_tmpl$5, _$escape(props.author.name)), _$createComponent(Show, {
337
+
338
+ // The same entries serve "…", right-click, the keyboard, and a long press. Alt+click and keys show at the entry's end.
339
+ // Each menu gets its own entries: a rendered shortcut is a DOM node and can live in only one menu.
340
+ const entries = () => (props.actions ?? []).map(entry => ({
341
+ label: entry.label,
342
+ icon: entry.icon,
343
+ description: entry.description,
344
+ disabled: entry.disabled,
345
+ variant: entry.variant,
346
+ gesture: entry.gesture,
347
+ immediate: entry.immediate,
348
+ trailing: entry.altClick ? _$createComponent(Kbd, {
349
+ keys: "alt+click"
350
+ }) : entry.shortcut ? _$createComponent(Kbd, {
351
+ get keys() {
352
+ return entry.shortcut;
353
+ }
354
+ }) : undefined,
355
+ action: () => entry.onSelect()
356
+ }));
357
+ const menuItems = createMemo(entries);
358
+ const gestureItems = createMemo(entries);
359
+ const hasMenu = () => (props.actions?.length ?? 0) > 0;
360
+
361
+ // Alt+click (Option+click) on the message, not on a link or control inside it, runs the entry that asks for it.
362
+ const altClick = event => {
363
+ if (!event.altKey || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey) return;
364
+ const entry = props.actions?.find(action => action.altClick && !action.disabled);
365
+ const target = event.target instanceof Element ? event.target : null;
366
+ if (!entry || target?.closest(ALT_CLICK_IGNORE)) return;
367
+ event.preventDefault();
368
+ entry.onSelect();
369
+ };
370
+ const more = () => _$createComponent(Dropdown.Root, {
371
+ get items() {
372
+ return menuItems();
373
+ },
374
+ get label() {
375
+ return chatMessages().messageActions;
376
+ },
377
+ "class": "k2b-message-row__menu-root",
378
+ get position() {
379
+ return props.own ? "bottom-right" : "bottom-left";
380
+ },
381
+ phone: "sheet",
382
+ get children() {
383
+ return _$createComponent(Dropdown.Trigger, {
384
+ iconOnly: true,
385
+ variant: "ghost",
386
+ size: "sm",
387
+ get label() {
388
+ return chatMessages().messageActions;
389
+ },
390
+ "class": "k2b-message-row__menu",
391
+ get children() {
392
+ return _$ssr(_tmpl$5);
393
+ }
394
+ });
395
+ }
396
+ });
397
+ const header = () => [_$ssr(_tmpl$6, _$escape(props.author.name)), _$createComponent(Show, {
327
398
  get when() {
328
399
  return props.badge;
329
400
  },
330
401
  get children() {
331
- return _$ssr(_tmpl$6, _$escape(props.badge));
402
+ return _$ssr(_tmpl$7, _$escape(props.badge));
332
403
  }
333
- }), _$ssr(_tmpl$7, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time))];
334
- const quote = value => [_$ssr(_tmpl$8), _$ssr(_tmpl$9, _$escape(chatMessages().messageReplyTo), _$escape(value.author), _$escape(value.text))];
404
+ }), _$ssr(_tmpl$8, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time))];
405
+ const quote = value => [_$ssr(_tmpl$9, _$escape(chatMessages().messageReplyTo), _$escape(value.author)), _$ssr(_tmpl$0, _$escape(value.text))];
406
+
407
+ /** The answered message on a quiet tint at the top of the bubble, or in its place without one. */
408
+ const quoteBlock = () => _$createComponent(Show, {
409
+ get when() {
410
+ return _$memo(() => !!content())() && props.quote;
411
+ },
412
+ children: value => _$createComponent(Show, {
413
+ get when() {
414
+ return value().onSelect;
415
+ },
416
+ get fallback() {
417
+ return _$ssr(_tmpl$1, _$escape(quote(value())));
418
+ },
419
+ children: select => _$ssr(_tmpl$10, _$escape(quote(value())))
420
+ })
421
+ });
335
422
 
336
423
  /** The picture's description, then that it is a video and how long, then how many more the grid hides. */
337
424
  const mediaLabel = (item, more) => [item.alt, item.kind === "video" ? [chatMessages().messageVideo, item.duration].filter(Boolean).join(" ") : "", more > 0 ? chatMessages().messageMoreAttachments({
@@ -356,17 +443,17 @@ export function MessageRow(props) {
356
443
  return item.href;
357
444
  },
358
445
  get children() {
359
- return [_$ssr(_tmpl$0, _$ssrAttribute("src", _$escape(attachmentUrl(item.src, true), true), false), _$ssrAttribute("width", item.width > 0 ? _$escape(item.width, true) : _$escape(undefined, true), false) + _$ssrAttribute("height", item.height > 0 ? _$escape(item.height, true) : _$escape(undefined, true), false)), _$createComponent(Show, {
446
+ return [_$ssr(_tmpl$11, _$ssrAttribute("src", _$escape(attachmentUrl(item.src, true), true), false), _$ssrAttribute("width", item.width > 0 ? _$escape(item.width, true) : _$escape(undefined, true), false) + _$ssrAttribute("height", item.height > 0 ? _$escape(item.height, true) : _$escape(undefined, true), false)), _$createComponent(Show, {
360
447
  get when() {
361
448
  return item.kind === "video";
362
449
  },
363
450
  get children() {
364
- return [_$ssr(_tmpl$1), _$createComponent(Show, {
451
+ return [_$ssr(_tmpl$12), _$createComponent(Show, {
365
452
  get when() {
366
453
  return item.duration;
367
454
  },
368
455
  get children() {
369
- return _$ssr(_tmpl$10, _$escape(item.duration));
456
+ return _$ssr(_tmpl$13, _$escape(item.duration));
370
457
  }
371
458
  })];
372
459
  }
@@ -375,23 +462,24 @@ export function MessageRow(props) {
375
462
  return more() > 0;
376
463
  },
377
464
  get children() {
378
- return _$ssr(_tmpl$11, _$escape(more()));
465
+ return _$ssr(_tmpl$14, _$escape(more()));
379
466
  }
380
467
  })];
381
468
  }
382
469
  });
383
470
  };
384
- return _$ssr(_tmpl$27, _$ssrAttribute("class", props.class ? `k2b-message-row ${_$escape(props.class, true)}` : "k2b-message-row", false) + _$ssrAttribute("data-own", props.own ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-group-start", groupStart() ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-status", _$escape(props.status, true), false) + _$ssrAttribute("data-media", media().length > 0 ? "" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
471
+ const row = // biome-ignore lint/a11y/noStaticElementInteractions lint/a11y/useKeyWithClickEvents: Alt+click is a pointer shortcut for a menu entry that the keyboard reaches through "…".
472
+ _$ssr(_tmpl$29, _$ssrAttribute("class", props.class ? `k2b-message-row ${_$escape(props.class, true)}` : "k2b-message-row", false) + _$ssrAttribute("data-own", props.own ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-group-start", groupStart() ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-status", _$escape(props.status, true), false) + _$ssrAttribute("data-media", media().length > 0 ? "" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
385
473
  get when() {
386
474
  return !props.own;
387
475
  },
388
476
  get children() {
389
- return _$ssr(_tmpl$13, _$escape(_$createComponent(Show, {
477
+ return _$ssr(_tmpl$16, _$escape(_$createComponent(Show, {
390
478
  get when() {
391
479
  return groupStart();
392
480
  },
393
481
  get children() {
394
- return _$ssr(_tmpl$12, _$escape(_$createComponent(Avatar, {
482
+ return _$ssr(_tmpl$15, _$escape(_$createComponent(Avatar, {
395
483
  get name() {
396
484
  return props.author.name;
397
485
  },
@@ -411,7 +499,7 @@ export function MessageRow(props) {
411
499
  return groupStart();
412
500
  },
413
501
  get fallback() {
414
- return _$ssr(_tmpl$28, _$escape(props.author.name), _$escape(props.time));
502
+ return _$ssr(_tmpl$30, _$escape(props.author.name), _$escape(props.time));
415
503
  },
416
504
  get children() {
417
505
  return _$createComponent(Show, {
@@ -419,10 +507,10 @@ export function MessageRow(props) {
419
507
  return !props.own;
420
508
  },
421
509
  get fallback() {
422
- return _$ssr(_tmpl$29, _$escape(props.author.name), _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
510
+ return _$ssr(_tmpl$31, _$escape(props.author.name), _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
423
511
  },
424
512
  get children() {
425
- return _$ssr(_tmpl$14, _$escape(header()));
513
+ return _$ssr(_tmpl$17, _$escape(header()));
426
514
  }
427
515
  });
428
516
  }
@@ -431,27 +519,21 @@ export function MessageRow(props) {
431
519
  return _$memo(() => !!content())() && props.forwarded;
432
520
  },
433
521
  get children() {
434
- return _$ssr(_tmpl$15, _$escape(chatMessages().messageForwarded));
522
+ return _$ssr(_tmpl$18, _$escape(chatMessages().messageForwarded));
435
523
  }
436
524
  })), _$escape(_$createComponent(Show, {
437
525
  get when() {
438
- return _$memo(() => !!content())() && props.quote;
526
+ return !hasBubble();
439
527
  },
440
- children: value => _$createComponent(Show, {
441
- get when() {
442
- return value().onSelect;
443
- },
444
- get fallback() {
445
- return _$ssr(_tmpl$30, _$escape(quote(value())));
446
- },
447
- children: select => _$ssr(_tmpl$31, _$escape(quote(value())))
448
- })
528
+ get children() {
529
+ return quoteBlock();
530
+ }
449
531
  })), _$escape(_$createComponent(Show, {
450
532
  get when() {
451
533
  return hasBubble();
452
534
  },
453
535
  get children() {
454
- return _$ssr(_tmpl$19, _$ssrAttribute("data-deleted", props.deleted ? "" : _$escape(undefined, true), false) + _$ssrAttribute("aria-busy", props.progress && !props.deleted ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
536
+ return _$ssr(_tmpl$22, _$ssrAttribute("data-deleted", props.deleted ? "" : _$escape(undefined, true), false) + _$ssrAttribute("aria-busy", props.progress && !props.deleted ? "true" : _$escape(undefined, true), false), _$escape(quoteBlock()), _$escape(_$createComponent(Show, {
455
537
  get when() {
456
538
  return !props.deleted;
457
539
  },
@@ -467,12 +549,12 @@ export function MessageRow(props) {
467
549
  return _$ssr(_tmpl$33);
468
550
  },
469
551
  get children() {
470
- return [_$ssr(_tmpl$16, _$ssrAttribute("id", _$escape(textId, true), false), _$ssrAttribute("data-collapsed", collapsed() ? "" : _$escape(undefined, true), false), rendered().html), _$createComponent(Show, {
552
+ return [_$ssr(_tmpl$19, _$ssrAttribute("id", _$escape(textId, true), false), _$ssrAttribute("data-collapsed", collapsed() ? "" : _$escape(undefined, true), false), rendered().html), _$createComponent(Show, {
471
553
  get when() {
472
554
  return collapsible();
473
555
  },
474
556
  get children() {
475
- return _$ssr(_tmpl$18, _$escape(_$createComponent(Button, {
557
+ return _$ssr(_tmpl$21, _$escape(_$createComponent(Button, {
476
558
  variant: "text",
477
559
  size: "xs",
478
560
  "class": "k2b-message-row__more",
@@ -489,7 +571,7 @@ export function MessageRow(props) {
489
571
  return props.edited;
490
572
  },
491
573
  get children() {
492
- return _$ssr(_tmpl$17, _$escape(chatMessages().messageEdited));
574
+ return _$ssr(_tmpl$20, _$escape(chatMessages().messageEdited));
493
575
  }
494
576
  })));
495
577
  }
@@ -497,21 +579,35 @@ export function MessageRow(props) {
497
579
  }
498
580
  });
499
581
  }
582
+ })), _$escape(_$createComponent(Show, {
583
+ get when() {
584
+ return hasMenu();
585
+ },
586
+ get children() {
587
+ return more();
588
+ }
500
589
  })));
501
590
  }
591
+ })), _$escape(_$createComponent(Show, {
592
+ get when() {
593
+ return _$memo(() => !!hasMenu())() && !hasBubble();
594
+ },
595
+ get children() {
596
+ return more();
597
+ }
502
598
  })), _$escape(_$createComponent(Show, {
503
599
  get when() {
504
600
  return _$memo(() => !!(content() && props.edited))() && !hasBubble();
505
601
  },
506
602
  get children() {
507
- return _$ssr(_tmpl$20, _$escape(chatMessages().messageEdited));
603
+ return _$ssr(_tmpl$23, _$escape(chatMessages().messageEdited));
508
604
  }
509
605
  })), _$escape(_$createComponent(Show, {
510
606
  get when() {
511
607
  return media().length > 0;
512
608
  },
513
609
  get children() {
514
- return _$ssr(_tmpl$21, _$ssrAttribute("aria-label", _$escape(chatMessages().attachments, true), false) + _$ssrAttribute("data-count", _$escape(Math.min(media().length, MEDIA_SHOWN), true), false), _$ssrStyle(media().length === 1 ? {
610
+ return _$ssr(_tmpl$24, _$ssrAttribute("aria-label", _$escape(chatMessages().attachments, true), false) + _$ssrAttribute("data-count", _$escape(Math.min(media().length, MEDIA_SHOWN), true), false), _$ssrStyle(media().length === 1 ? {
515
611
  width: mediaWidth(media()[0])
516
612
  } : undefined), _$escape(_$createComponent(For, {
517
613
  get each() {
@@ -525,7 +621,7 @@ export function MessageRow(props) {
525
621
  return files().length > 0;
526
622
  },
527
623
  get children() {
528
- return _$ssr(_tmpl$22, _$escape(_$createComponent(For, {
624
+ return _$ssr(_tmpl$25, _$escape(_$createComponent(For, {
529
625
  get each() {
530
626
  return files();
531
627
  },
@@ -555,14 +651,14 @@ export function MessageRow(props) {
555
651
  return _$memo(() => !!content())() && props.linkPreview;
556
652
  },
557
653
  get children() {
558
- return _$ssr(_tmpl$23, _$escape(props.linkPreview));
654
+ return _$ssr(_tmpl$26, _$escape(props.linkPreview));
559
655
  }
560
656
  })), _$escape(_$createComponent(Show, {
561
657
  get when() {
562
658
  return _$memo(() => !!content())() && props.card;
563
659
  },
564
660
  get children() {
565
- return _$ssr(_tmpl$23, _$escape(props.card));
661
+ return _$ssr(_tmpl$26, _$escape(props.card));
566
662
  }
567
663
  })), _$escape(_$createComponent(Show, {
568
664
  get when() {
@@ -601,12 +697,21 @@ export function MessageRow(props) {
601
697
  time: time()
602
698
  })))
603
699
  })))
700
+ })), _$escape(_$createComponent(Show, {
701
+ get when() {
702
+ return props.origin;
703
+ },
704
+ children: origin => _$createComponent(OriginChip, {
705
+ get origin() {
706
+ return origin();
707
+ }
708
+ })
604
709
  })), _$escape(_$createComponent(Show, {
605
710
  get when() {
606
711
  return hasFooter();
607
712
  },
608
713
  get children() {
609
- return _$ssr(_tmpl$25, _$escape(_$createComponent(Show, {
714
+ return _$ssr(_tmpl$28, _$escape(_$createComponent(Show, {
610
715
  get when() {
611
716
  return reactions();
612
717
  },
@@ -626,7 +731,7 @@ export function MessageRow(props) {
626
731
  return hasLine();
627
732
  },
628
733
  get children() {
629
- return _$ssr(_tmpl$24, _$escape(_$createComponent(Show, {
734
+ return _$ssr(_tmpl$27, _$escape(_$createComponent(Show, {
630
735
  get when() {
631
736
  return props.progress;
632
737
  },
@@ -655,6 +760,18 @@ export function MessageRow(props) {
655
760
  return chatMessages().messageRetry;
656
761
  }
657
762
  })
763
+ }), _$createComponent(Show, {
764
+ get when() {
765
+ return props.onDiscard;
766
+ },
767
+ children: discard => _$createComponent(Button, {
768
+ variant: "text",
769
+ size: "xs",
770
+ onClick: () => discard()(),
771
+ get children() {
772
+ return chatMessages().messageDiscard;
773
+ }
774
+ })
658
775
  })];
659
776
  }
660
777
  }), _$createComponent(Show, {
@@ -698,46 +815,102 @@ export function MessageRow(props) {
698
815
  }
699
816
  })));
700
817
  }
701
- })), _$escape(_$createComponent(Show, {
818
+ })));
819
+ return _$createComponent(Show, {
702
820
  get when() {
703
- return (props.actions?.length ?? 0) > 0;
821
+ return hasMenu();
704
822
  },
823
+ fallback: row,
705
824
  get children() {
706
- return _$ssr(_tmpl$26, _$ssrAttribute("aria-label", _$escape(chatMessages().messageActions, true), false), _$escape(_$createComponent(For, {
707
- get each() {
708
- return props.actions;
825
+ return _$createComponent(GestureMenu, {
826
+ get items() {
827
+ return gestureItems();
709
828
  },
710
- children: action => _$createComponent(IconButton, {
711
- get label() {
712
- return action.label;
713
- },
714
- size: "sm",
715
- get disabled() {
716
- return action.disabled;
717
- },
718
- onClick: () => action.onSelect(),
719
- get children() {
720
- return _$ssr(_tmpl$49, _$ssrAttribute("class", _$escape(action.icon, true), false));
721
- }
722
- })
723
- })));
829
+ get label() {
830
+ return chatMessages().messageMenu({
831
+ author: props.author.name,
832
+ time: props.time
833
+ });
834
+ },
835
+ tabIndex: -1,
836
+ children: row
837
+ });
838
+ }
839
+ });
840
+ }
841
+
842
+ /** Where a row belongs, such as its thread; a control when it opens that place. */
843
+ function OriginChip(props) {
844
+ return _$createComponent(Show, {
845
+ get when() {
846
+ return props.origin.onSelect;
847
+ },
848
+ get fallback() {
849
+ return _$ssr(_tmpl$49, _$escape(_$createComponent(Show, {
850
+ get when() {
851
+ return props.origin.icon;
852
+ },
853
+ children: icon => _$ssr(_tmpl$50, _$ssrAttribute("class", _$escape(icon(), true), false))
854
+ })), _$escape(props.origin.label));
855
+ },
856
+ children: select => _$ssr(_tmpl$51, _$ssrAttribute("aria-label", _$escape(props.origin.selectLabel, true), false), _$escape(_$createComponent(Show, {
857
+ get when() {
858
+ return props.origin.icon;
859
+ },
860
+ children: icon => _$ssr(_tmpl$50, _$ssrAttribute("class", _$escape(icon(), true), false))
861
+ })), _$escape(props.origin.label))
862
+ });
863
+ }
864
+
865
+ /**
866
+ * A quiet line for a change to something the conversation is about, such as a task's new status: no bubble, aligned
867
+ * with the messages' text, with its time at the end. It is no message: it never counts as unread.
868
+ */
869
+ export function MessageEventRow(props) {
870
+ return _$ssr(_tmpl$53, _$ssrAttribute("class", props.class ? `k2b-message-event-row ${_$escape(props.class, true)}` : "k2b-message-event-row", false), _$ssrAttribute("class", _$escape(props.icon ?? "ti ti-point", true), false), _$escape(props.children), _$escape(_$createComponent(Show, {
871
+ get when() {
872
+ return props.origin;
873
+ },
874
+ children: origin => _$createComponent(OriginChip, {
875
+ get origin() {
876
+ return origin();
877
+ }
878
+ })
879
+ })), _$escape(_$createComponent(Show, {
880
+ get when() {
881
+ return props.time;
882
+ },
883
+ get children() {
884
+ return _$ssr(_tmpl$52, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
724
885
  }
725
886
  })));
726
887
  }
727
888
 
889
+ /** Several event lines in a row as one line that opens them, such as "4 changes to Invitation and Light test". */
890
+ export function MessageEventGroup(props) {
891
+ return _$ssr(_tmpl$54, _$ssrAttribute("class", props.class ? `k2b-message-event-row k2b-message-event-group ${_$escape(props.class, true)}` : "k2b-message-event-row k2b-message-event-group", false) + _$ssrAttribute("aria-expanded", _$escape(props.expanded, true), false), _$escape(props.label), _$escape(_$createComponent(Show, {
892
+ get when() {
893
+ return props.time;
894
+ },
895
+ get children() {
896
+ return _$ssr(_tmpl$52, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
897
+ }
898
+ })), _$ssrAttribute("class", props.expanded ? "ti ti-chevron-up" : "ti ti-chevron-down", false));
899
+ }
900
+
728
901
  /** A quiet, centered line for something that happened in the conversation, such as a person joining. */
729
902
  export function MessageSystemRow(props) {
730
- return _$ssr(_tmpl$51, _$ssrAttribute("class", props.class ? `k2b-message-system-row ${_$escape(props.class, true)}` : "k2b-message-system-row", false), _$escape(_$createComponent(Show, {
903
+ return _$ssr(_tmpl$55, _$ssrAttribute("class", props.class ? `k2b-message-system-row ${_$escape(props.class, true)}` : "k2b-message-system-row", false), _$escape(_$createComponent(Show, {
731
904
  get when() {
732
905
  return props.icon;
733
906
  },
734
- children: icon => _$ssr(_tmpl$49, _$ssrAttribute("class", _$escape(icon(), true), false))
907
+ children: icon => _$ssr(_tmpl$50, _$ssrAttribute("class", _$escape(icon(), true), false))
735
908
  })), _$escape(props.children), _$escape(_$createComponent(Show, {
736
909
  get when() {
737
910
  return props.time;
738
911
  },
739
912
  get children() {
740
- return _$ssr(_tmpl$50, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
913
+ return _$ssr(_tmpl$52, _$ssrAttribute("datetime", _$escape(dateTimeOf(props.dateTime), true), false), _$escape(props.time));
741
914
  }
742
915
  })));
743
916
  }