@tutti-os/ui-rich-text 0.0.23 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,21 @@
1
1
  import {
2
- DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE,
3
- RICH_TEXT_AT_ALL_FILTER_ID,
4
2
  activityMentionStatusBadgeClassName,
5
3
  activityMentionStatusTone,
6
- buildDefaultRichTextTriggerProviderGroups,
7
- buildMentionPaletteState,
8
- buildRichTextAtFilterTabs,
9
- findRichTextTriggerProviderGroup,
4
+ buildMentionPaletteModel,
5
+ buildMentionPaletteModelFromTriggerMatches,
6
+ findMentionPaletteEntry,
10
7
  flattenMentionPaletteEntries,
11
- groupRichTextAtMatches,
12
8
  issueMentionStatusBadgeClassName,
13
9
  issueMentionStatusTone,
10
+ mentionPaletteGroup,
14
11
  mentionStatusBadgeClassName,
15
- normalizeAtPanelQuery,
12
+ moveMentionPaletteHighlight,
13
+ nextMentionPaletteCategory,
14
+ repairMentionPaletteHighlight,
16
15
  resolveMentionFileThumbnailUrl,
17
16
  resolveMentionFileVisualKind,
18
- richTextAtGroupExpandCount
19
- } from "../chunk-E4PWFY3N.js";
17
+ selectedMentionPaletteItem
18
+ } from "../chunk-3ZXEASYU.js";
20
19
 
21
20
  // src/at-panel/MentionPalette.tsx
22
21
  import {
@@ -28,7 +27,7 @@ import {
28
27
  FolderFailedFilledIcon,
29
28
  KeyboardFilledIcon
30
29
  } from "@tutti-os/ui-system/icons";
31
- import { Spinner, UnderlineTabs } from "@tutti-os/ui-system/components";
30
+ import { UnderlineTabs } from "@tutti-os/ui-system/components";
32
31
  import { cn as cn2 } from "@tutti-os/ui-system/utils";
33
32
 
34
33
  // src/at-panel/mentionPaletteScrollbar.tsx
@@ -256,15 +255,33 @@ function resolveMentionPaletteTheme(theme) {
256
255
  groupDividerAttribute: theme?.groupDividerAttribute ?? DEFAULT_THEME.groupDividerAttribute
257
256
  };
258
257
  }
258
+ function mentionPaletteRootClassName(theme) {
259
+ return cn2(
260
+ DEFAULT_THEME.classNames.palette,
261
+ theme.classNames.palette,
262
+ paletteStyles.palette
263
+ );
264
+ }
259
265
  var paletteStyles = {
260
- palette: "nodrag grid h-full max-h-[320px] min-h-0 grid-rows-[auto_minmax(0,1fr)_auto] overflow-hidden text-[13px] [-webkit-app-region:no-drag]",
261
- header: "relative z-10 shrink-0",
262
- footer: "shrink-0",
263
- scrollShell: "relative min-h-0 overflow-hidden",
264
- scrollBody: "h-full min-h-0 overflow-y-auto overscroll-contain px-1 pb-1 pt-2",
265
- rowButton: "nodrag relative flex min-h-9 w-full min-w-0 cursor-pointer select-none items-center gap-1.5 overflow-hidden rounded-[6px] border-0 bg-transparent px-2.5 py-2 text-left text-[13px] text-[var(--text-primary)] outline-hidden transition-colors duration-200 [-webkit-app-region:no-drag] active:bg-[var(--transparency-active)] data-[highlighted]:bg-[var(--transparency-block)] data-[highlighted]:text-[var(--text-primary)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:min-w-0 *:[span]:last:flex-1 *:[span]:last:items-center *:[span]:last:gap-2",
266
- categoryButton: "nodrag flex min-h-[72px] w-full items-center gap-3.5 rounded-[6px] border-0 bg-transparent px-2.5 py-2.5 text-left text-[var(--text-primary)] transition-[background-color,color] hover:bg-[var(--transparency-block)] focus-visible:bg-[var(--transparency-block)] focus-visible:outline-none active:bg-[var(--transparency-active)]",
267
- expandButton: "nodrag flex w-full items-center justify-center rounded-[6px] px-3 py-2 text-[13px] font-medium text-[var(--text-secondary)] transition focus-visible:outline-none active:bg-[var(--transparency-active)] data-[highlighted]:bg-[var(--transparency-block)] data-[highlighted]:text-[var(--text-primary)]"
266
+ palette: "rich-text-at-mention-palette__shell",
267
+ header: "rich-text-at-mention-palette__header",
268
+ footer: "rich-text-at-mention-palette__footer",
269
+ scrollShell: "rich-text-at-mention-palette__scroll-shell",
270
+ scrollBody: "rich-text-at-mention-palette__scroll-body",
271
+ groups: "rich-text-at-mention-palette__groups",
272
+ group: "rich-text-at-mention-palette__group",
273
+ groupDivider: "rich-text-at-mention-palette__group-divider",
274
+ groupLabel: "rich-text-at-mention-palette__group-label",
275
+ groupItems: "rich-text-at-mention-palette__group-items",
276
+ groupEmpty: "rich-text-at-mention-palette__group-empty",
277
+ rowButton: "rich-text-at-mention-palette__row-button",
278
+ expandButton: "rich-text-at-mention-palette__expand-button",
279
+ emptyState: "rich-text-at-mention-palette__empty-state",
280
+ emptyStateInner: "rich-text-at-mention-palette__empty-state-inner",
281
+ emptyStateIcon: "rich-text-at-mention-palette__empty-state-icon",
282
+ emptyStateText: "rich-text-at-mention-palette__empty-state-text",
283
+ loading: "rich-text-at-mention-palette__loading",
284
+ loadingSpinner: "rich-text-at-mention-palette__loading-spinner"
268
285
  };
269
286
  var MENTION_PALETTE_LOADING_MIN_VISIBLE_MS = 320;
270
287
  function MentionPalette(props) {
@@ -318,10 +335,14 @@ function MentionPalette(props) {
318
335
  highlightedElement.scrollIntoView({ block: "nearest" });
319
336
  return;
320
337
  }
321
- if (!scrollHighlightedIntoViewCentered) {
338
+ if (scrollHighlightedIntoViewCentered) {
339
+ centerElementInScrollContainer(scrollContainer, highlightedElement);
322
340
  return;
323
341
  }
324
- centerElementInScrollContainer(scrollContainer, highlightedElement);
342
+ scrollElementIntoScrollContainerNearest(
343
+ scrollContainer,
344
+ highlightedElement
345
+ );
325
346
  }, [highlightedKey, scrollHighlightedIntoViewCentered]);
326
347
  useEffect2(() => {
327
348
  if (loadingHideTimerRef.current !== null) {
@@ -354,7 +375,7 @@ function MentionPalette(props) {
354
375
  return /* @__PURE__ */ jsx2(
355
376
  "div",
356
377
  {
357
- className: cn2(theme.classNames.palette, paletteStyles.palette),
378
+ className: mentionPaletteRootClassName(theme),
358
379
  style: paletteMaxHeightStyle,
359
380
  role: "listbox",
360
381
  "aria-label": labels.listbox ?? labels.tabHint,
@@ -408,7 +429,7 @@ function MentionPalette(props) {
408
429
  return /* @__PURE__ */ jsxs(
409
430
  "div",
410
431
  {
411
- className: cn2(theme.classNames.palette, paletteStyles.palette),
432
+ className: mentionPaletteRootClassName(theme),
412
433
  style: paletteMaxHeightStyle,
413
434
  role: "listbox",
414
435
  "aria-label": labels.listbox ?? labels.tabHint,
@@ -480,6 +501,26 @@ function centerElementInScrollContainer(container, element) {
480
501
  const nextScrollTop = Math.min(Math.max(0, centeredScrollTop), maxScrollTop);
481
502
  container.scrollTo({ top: nextScrollTop, behavior: "auto" });
482
503
  }
504
+ function scrollElementIntoScrollContainerNearest(container, element) {
505
+ const containerRect = container.getBoundingClientRect();
506
+ const elementRect = element.getBoundingClientRect();
507
+ let nextScrollTop = container.scrollTop;
508
+ if (elementRect.top < containerRect.top) {
509
+ nextScrollTop -= containerRect.top - elementRect.top;
510
+ } else if (elementRect.bottom > containerRect.bottom) {
511
+ nextScrollTop += elementRect.bottom - containerRect.bottom;
512
+ } else {
513
+ return;
514
+ }
515
+ const maxScrollTop = Math.max(
516
+ 0,
517
+ container.scrollHeight - container.clientHeight
518
+ );
519
+ container.scrollTo({
520
+ top: Math.min(Math.max(0, nextScrollTop), maxScrollTop),
521
+ behavior: "auto"
522
+ });
523
+ }
483
524
  function findGroup(groups, groupId) {
484
525
  const group = groups.find((candidate) => candidate.id === groupId);
485
526
  if (!group) {
@@ -499,25 +540,25 @@ function MentionPaletteGroups({
499
540
  renderListFooter,
500
541
  groupDividerAttribute
501
542
  }) {
502
- return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
543
+ return /* @__PURE__ */ jsxs("div", { className: paletteStyles.groups, children: [
503
544
  state.groups.map((group, index) => {
504
545
  const showGroupDivider = index > 0 && !group.hideTopDivider;
505
546
  return /* @__PURE__ */ jsxs(
506
547
  "section",
507
548
  {
508
- className: cn2("grid gap-1", group.sectionClassName),
549
+ className: cn2(paletteStyles.group, group.sectionClassName),
509
550
  children: [
510
551
  showGroupDivider ? /* @__PURE__ */ jsx2(
511
552
  "div",
512
553
  {
513
- className: "mx-3 mb-2 border-t border-[var(--line-1)]",
554
+ className: paletteStyles.groupDivider,
514
555
  ...{ [groupDividerAttribute]: "true" },
515
556
  "aria-hidden": "true"
516
557
  }
517
558
  ) : null,
518
- group.label ? /* @__PURE__ */ jsx2("div", { className: "px-3 text-[13px] font-normal text-[var(--text-secondary)]", children: group.label }) : null,
519
- /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
520
- group.items.length === 0 && group.emptyLabel ? /* @__PURE__ */ jsx2("div", { className: "px-3 py-1 text-[13px] font-normal text-[var(--text-tertiary)]", children: group.emptyLabel }) : null,
559
+ group.label ? /* @__PURE__ */ jsx2("div", { className: paletteStyles.groupLabel, children: group.label }) : null,
560
+ /* @__PURE__ */ jsxs("div", { className: paletteStyles.groupItems, children: [
561
+ group.items.length === 0 && group.emptyLabel ? /* @__PURE__ */ jsx2("div", { className: paletteStyles.groupEmpty, children: group.emptyLabel }) : null,
521
562
  group.items.map((item) => {
522
563
  const entryKey = `${group.id}:${getItemKey(item, group)}`;
523
564
  const isHighlighted = entryKey === highlightedKey;
@@ -526,14 +567,15 @@ function MentionPaletteGroups({
526
567
  {
527
568
  ref: isHighlighted ? highlightedOptionRef : null,
528
569
  type: "button",
529
- className: cn2(
530
- paletteStyles.rowButton,
531
- isHighlighted && "bg-[var(--transparency-block)]"
532
- ),
570
+ className: paletteStyles.rowButton,
533
571
  role: "option",
534
572
  "aria-selected": isHighlighted,
535
573
  "data-highlighted": isHighlighted ? "" : void 0,
536
- onMouseEnter: () => onHighlightChange(entryKey),
574
+ onPointerMove: () => {
575
+ if (!isHighlighted) {
576
+ onHighlightChange(entryKey);
577
+ }
578
+ },
537
579
  onMouseDown: (event) => event.preventDefault(),
538
580
  onClick: () => onSelectItem(item, group),
539
581
  children: renderItem(item, { active: isHighlighted })
@@ -546,12 +588,13 @@ function MentionPaletteGroups({
546
588
  {
547
589
  ref: `expand:${group.id}` === highlightedKey ? highlightedOptionRef : null,
548
590
  type: "button",
549
- className: cn2(
550
- paletteStyles.expandButton,
551
- `expand:${group.id}` === highlightedKey && "bg-[var(--transparency-block)] text-[var(--text-primary)]"
552
- ),
591
+ className: paletteStyles.expandButton,
553
592
  "data-highlighted": `expand:${group.id}` === highlightedKey ? "" : void 0,
554
- onMouseEnter: () => onHighlightChange(`expand:${group.id}`),
593
+ onPointerMove: () => {
594
+ if (`expand:${group.id}` !== highlightedKey) {
595
+ onHighlightChange(`expand:${group.id}`);
596
+ }
597
+ },
555
598
  onMouseDown: (event) => event.preventDefault(),
556
599
  onClick: () => onExpandGroup(group.id),
557
600
  children: group.expandLabel ?? `+${Math.max(0, group.totalCount - group.visibleCount)}`
@@ -577,18 +620,18 @@ function MentionPaletteEmptyState({
577
620
  return /* @__PURE__ */ jsx2(
578
621
  "div",
579
622
  {
580
- className: "flex h-full min-h-0 flex-1 items-center justify-center px-4 py-6 text-center text-[13px] text-[var(--text-tertiary)]",
623
+ className: paletteStyles.emptyState,
581
624
  "data-empty-state-icon": icon,
582
625
  "data-testid": testId,
583
- children: /* @__PURE__ */ jsxs("div", { className: "flex max-w-[28ch] flex-col items-center justify-center gap-3", children: [
626
+ children: /* @__PURE__ */ jsxs("div", { className: paletteStyles.emptyStateInner, children: [
584
627
  /* @__PURE__ */ jsx2(
585
628
  EmptyStateIcon,
586
629
  {
587
- className: "h-6 w-6 text-[var(--text-tertiary)]",
630
+ className: paletteStyles.emptyStateIcon,
588
631
  "aria-hidden": "true"
589
632
  }
590
633
  ),
591
- /* @__PURE__ */ jsx2("span", { className: "leading-5 text-[var(--text-tertiary)]", children: label })
634
+ /* @__PURE__ */ jsx2("span", { className: paletteStyles.emptyStateText, children: label })
592
635
  ] })
593
636
  }
594
637
  );
@@ -598,13 +641,13 @@ function MentionPaletteLoading({
598
641
  spinnerTestId
599
642
  }) {
600
643
  "use memo";
601
- return /* @__PURE__ */ jsxs("div", { className: "flex min-h-[52px] items-center gap-2 rounded-xl px-3 text-[13px] text-[var(--text-secondary)]", children: [
644
+ return /* @__PURE__ */ jsxs("div", { className: paletteStyles.loading, children: [
602
645
  /* @__PURE__ */ jsx2(
603
- Spinner,
646
+ "span",
604
647
  {
605
- size: 16,
606
- className: "text-[var(--text-secondary)]",
607
- testId: spinnerTestId
648
+ "aria-hidden": "true",
649
+ className: paletteStyles.loadingSpinner,
650
+ "data-testid": spinnerTestId
608
651
  }
609
652
  ),
610
653
  /* @__PURE__ */ jsx2("span", { children: label })
@@ -627,20 +670,52 @@ function MentionPaletteHint({
627
670
  "aria-label": ariaLabel,
628
671
  "data-testid": testId,
629
672
  children: [
630
- /* @__PURE__ */ jsxs(
631
- "button",
632
- {
633
- className: cn2(classNames.hintItem, classNames.hintButton),
634
- type: "button",
635
- "aria-label": cycleFilterLabel,
636
- onMouseDown: (event) => event.preventDefault(),
637
- onClick: () => onCycleFilter(1),
638
- children: [
639
- /* @__PURE__ */ jsx2("kbd", { className: classNames.shortcut, children: "Tab" }),
640
- /* @__PURE__ */ jsx2("span", { children: cycleFilterLabel })
641
- ]
642
- }
643
- ),
673
+ /* @__PURE__ */ jsxs("span", { className: classNames.hintItem, children: [
674
+ /* @__PURE__ */ jsxs("span", { className: classNames.shortcutGroup, children: [
675
+ /* @__PURE__ */ jsx2(
676
+ "button",
677
+ {
678
+ className: cn2(classNames.shortcut, classNames.shortcutButton),
679
+ type: "button",
680
+ "aria-label": `Tab ${cycleFilterLabel}`,
681
+ onMouseDown: (event) => event.preventDefault(),
682
+ onClick: () => onCycleFilter(1),
683
+ children: "Tab"
684
+ }
685
+ ),
686
+ /* @__PURE__ */ jsx2(
687
+ "button",
688
+ {
689
+ className: cn2(
690
+ classNames.shortcut,
691
+ classNames.shortcutArrow,
692
+ classNames.shortcutButton
693
+ ),
694
+ type: "button",
695
+ "aria-label": `\u2190 ${cycleFilterLabel}`,
696
+ onMouseDown: (event) => event.preventDefault(),
697
+ onClick: () => onCycleFilter(-1),
698
+ children: "\u2190"
699
+ }
700
+ ),
701
+ /* @__PURE__ */ jsx2(
702
+ "button",
703
+ {
704
+ className: cn2(
705
+ classNames.shortcut,
706
+ classNames.shortcutArrow,
707
+ classNames.shortcutButton
708
+ ),
709
+ type: "button",
710
+ "aria-label": `\u2192 ${cycleFilterLabel}`,
711
+ onMouseDown: (event) => event.preventDefault(),
712
+ onClick: () => onCycleFilter(1),
713
+ children: "\u2192"
714
+ }
715
+ )
716
+ ] }),
717
+ /* @__PURE__ */ jsx2("span", { children: cycleFilterLabel })
718
+ ] }),
644
719
  /* @__PURE__ */ jsx2("span", { className: classNames.hintSeparator, "aria-hidden": "true", children: "\uFF5C" }),
645
720
  /* @__PURE__ */ jsxs("span", { className: classNames.hintItem, children: [
646
721
  /* @__PURE__ */ jsxs("span", { className: classNames.shortcutGroup, children: [
@@ -682,6 +757,193 @@ function MentionPaletteHint({
682
757
  );
683
758
  }
684
759
 
760
+ // src/at-panel/mentionPaletteStateAdapter.ts
761
+ function createMentionPaletteStateAdapter(input) {
762
+ const getPaletteItemKey = (item, group) => input.getItemKey(item, group.id);
763
+ const selectCategory = (categoryId) => {
764
+ input.callbacks?.onActiveCategoryIdChange?.(categoryId);
765
+ };
766
+ const expandGroup = (groupId) => {
767
+ input.callbacks?.onExpandGroup?.(groupId);
768
+ };
769
+ const moveSelection = (delta) => {
770
+ const nextKey = moveMentionPaletteHighlight({
771
+ state: input.state,
772
+ currentKey: input.highlightedKey,
773
+ delta,
774
+ getItemKey: input.getItemKey
775
+ });
776
+ if (nextKey !== null) {
777
+ input.callbacks?.onHighlightChange?.(nextKey);
778
+ }
779
+ return nextKey;
780
+ };
781
+ const cycleCategory = (delta) => {
782
+ const cycleCategories = resolveCycleCategories(input.categoryCycleOrder);
783
+ const categories = cycleCategories.length ? cycleCategories : input.state.categories;
784
+ if (categories.length === 0) {
785
+ return null;
786
+ }
787
+ const nextCategoryId = nextMentionPaletteCategory(
788
+ categories,
789
+ input.state.filter,
790
+ delta
791
+ );
792
+ selectCategory(nextCategoryId);
793
+ return nextCategoryId;
794
+ };
795
+ const selectedItem = selectedMentionPaletteItem({
796
+ state: input.state,
797
+ key: input.highlightedKey,
798
+ getItemKey: input.getItemKey
799
+ });
800
+ const commitHighlighted = () => {
801
+ const activeEntry = findMentionPaletteEntry({
802
+ state: input.state,
803
+ key: input.highlightedKey,
804
+ getItemKey: input.getItemKey
805
+ });
806
+ const fallbackCategoryId = categoryIdFromKey(input.highlightedKey);
807
+ if (!activeEntry) {
808
+ if (fallbackCategoryId !== null && input.state.categories.some(
809
+ (category) => category.id === fallbackCategoryId
810
+ )) {
811
+ selectCategory(fallbackCategoryId);
812
+ return { type: "category", categoryId: fallbackCategoryId };
813
+ }
814
+ return { type: "none" };
815
+ }
816
+ if (activeEntry.type === "category" && activeEntry.categoryId) {
817
+ selectCategory(activeEntry.categoryId);
818
+ return { type: "category", categoryId: activeEntry.categoryId };
819
+ }
820
+ if (activeEntry.type === "expand" && activeEntry.groupId) {
821
+ expandGroup(activeEntry.groupId);
822
+ return { type: "expand", groupId: activeEntry.groupId };
823
+ }
824
+ if (activeEntry.type === "item") {
825
+ const item = selectedMentionPaletteItem({
826
+ state: input.state,
827
+ key: activeEntry.key,
828
+ getItemKey: input.getItemKey
829
+ });
830
+ if (item !== null) {
831
+ input.callbacks?.onSelectItem?.(item);
832
+ return { type: "item", item };
833
+ }
834
+ }
835
+ return { type: "none" };
836
+ };
837
+ return {
838
+ selectedItem,
839
+ paletteProps: {
840
+ state: input.state,
841
+ highlightedKey: input.highlightedKey,
842
+ getItemKey: getPaletteItemKey,
843
+ onHighlightChange: (key) => {
844
+ input.callbacks?.onHighlightChange?.(key);
845
+ },
846
+ onSelectItem: (item) => {
847
+ input.callbacks?.onSelectItem?.(item);
848
+ },
849
+ onSelectCategory: selectCategory,
850
+ onSelectFilter: selectCategory,
851
+ onExpandGroup: expandGroup,
852
+ onCycleFilter: cycleCategory,
853
+ onMoveSelection: moveSelection
854
+ },
855
+ moveSelection,
856
+ selectCategory,
857
+ expandGroup,
858
+ cycleCategory,
859
+ commitHighlighted
860
+ };
861
+ }
862
+ function resolveCycleCategories(categories) {
863
+ return categories?.map(
864
+ (category) => typeof category === "string" ? { id: category } : category
865
+ ) ?? [];
866
+ }
867
+ function categoryIdFromKey(key) {
868
+ const prefix = "category:";
869
+ return key?.startsWith(prefix) ? key.slice(prefix.length) : null;
870
+ }
871
+
872
+ // src/at-panel/MentionPaletteFromState.tsx
873
+ import { jsx as jsx3 } from "react/jsx-runtime";
874
+ function MentionPaletteFromState(props) {
875
+ "use memo";
876
+ const {
877
+ labels,
878
+ hintLabels,
879
+ maxHeightPx,
880
+ renderItem,
881
+ renderListFooter,
882
+ loadingBanner,
883
+ scrollHighlightedIntoViewCentered,
884
+ theme,
885
+ ...adapterInput
886
+ } = props;
887
+ const adapter = createMentionPaletteStateAdapter(adapterInput);
888
+ return /* @__PURE__ */ jsx3(
889
+ MentionPalette,
890
+ {
891
+ ...adapter.paletteProps,
892
+ labels,
893
+ hintLabels,
894
+ maxHeightPx,
895
+ renderItem,
896
+ renderListFooter,
897
+ loadingBanner,
898
+ scrollHighlightedIntoViewCentered,
899
+ theme
900
+ }
901
+ );
902
+ }
903
+
904
+ // src/at-panel/MentionPaletteControls.tsx
905
+ import { CheckIcon } from "@tutti-os/ui-system/icons";
906
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
907
+ function MentionPaletteSelectIndicator(props) {
908
+ return /* @__PURE__ */ jsx4(
909
+ "span",
910
+ {
911
+ "aria-hidden": "true",
912
+ className: "rich-text-at-mention-select-indicator",
913
+ "data-selected": props.selected ? "true" : "false",
914
+ children: /* @__PURE__ */ jsx4(CheckIcon, { size: 13 })
915
+ }
916
+ );
917
+ }
918
+ function MentionPaletteMultiSelectFooter(props) {
919
+ return /* @__PURE__ */ jsxs2("div", { className: "rich-text-at-mention-multiselect-footer", children: [
920
+ /* @__PURE__ */ jsx4("span", { className: "rich-text-at-mention-multiselect-footer__count", children: props.countLabel }),
921
+ /* @__PURE__ */ jsxs2("div", { className: "rich-text-at-mention-multiselect-footer__actions", children: [
922
+ /* @__PURE__ */ jsx4(
923
+ "button",
924
+ {
925
+ type: "button",
926
+ className: "rich-text-at-mention-multiselect-footer__button rich-text-at-mention-multiselect-footer__button--secondary",
927
+ onMouseDown: (event) => event.preventDefault(),
928
+ onClick: props.onCancel,
929
+ children: props.cancelLabel
930
+ }
931
+ ),
932
+ /* @__PURE__ */ jsx4(
933
+ "button",
934
+ {
935
+ type: "button",
936
+ disabled: props.count === 0,
937
+ className: "rich-text-at-mention-multiselect-footer__button rich-text-at-mention-multiselect-footer__button--primary",
938
+ onMouseDown: (event) => event.preventDefault(),
939
+ onClick: props.onConfirm,
940
+ children: props.confirmLabel
941
+ }
942
+ )
943
+ ] })
944
+ ] });
945
+ }
946
+
685
947
  // src/at-panel/MentionRow.tsx
686
948
  import {
687
949
  ArrowLeftIcon,
@@ -738,7 +1000,7 @@ function mentionRowDataAttribute(mode, key, value) {
738
1000
  }
739
1001
 
740
1002
  // src/at-panel/MentionRow.tsx
741
- import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1003
+ import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
742
1004
  var MENTION_FILE_VISUAL_KIND_ICON = {
743
1005
  back: ArrowLeftIcon,
744
1006
  folder: FolderIcon,
@@ -789,7 +1051,7 @@ function renderMentionRow(item, options) {
789
1051
  openReferencesLabel
790
1052
  } = resolveMentionRowRenderOptions(options);
791
1053
  const resolved = resolveMentionRowClassNames(classNames);
792
- const referencesButton = onOpenReferences ? /* @__PURE__ */ jsx3(
1054
+ const referencesButton = onOpenReferences ? /* @__PURE__ */ jsx5(
793
1055
  MentionOpenReferencesButton,
794
1056
  {
795
1057
  label: openReferencesLabel,
@@ -798,7 +1060,7 @@ function renderMentionRow(item, options) {
798
1060
  }
799
1061
  ) : null;
800
1062
  if (item.kind === "file") {
801
- return /* @__PURE__ */ jsx3(
1063
+ return /* @__PURE__ */ jsx5(
802
1064
  MentionFileRow,
803
1065
  {
804
1066
  item,
@@ -807,10 +1069,19 @@ function renderMentionRow(item, options) {
807
1069
  }
808
1070
  );
809
1071
  }
1072
+ if (item.kind === "plain") {
1073
+ return /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row rich-text-at-mention-row--plain", children: [
1074
+ item.leading,
1075
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__text-stack", children: [
1076
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__title", children: item.label }),
1077
+ item.description ? /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__description", children: item.description }) : null
1078
+ ] })
1079
+ ] });
1080
+ }
810
1081
  if (item.kind === "session") {
811
- return /* @__PURE__ */ jsxs2("span", { className: "grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-3", children: [
812
- /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-2 overflow-hidden", children: [
813
- /* @__PURE__ */ jsx3(
1082
+ return /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row rich-text-at-mention-row--session", children: [
1083
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__leading", children: [
1084
+ /* @__PURE__ */ jsx5(
814
1085
  MentionSessionAvatarStack,
815
1086
  {
816
1087
  item,
@@ -818,9 +1089,9 @@ function renderMentionRow(item, options) {
818
1089
  dataAttributeMode
819
1090
  }
820
1091
  ),
821
- /* @__PURE__ */ jsx3("span", { className: "min-w-0 truncate text-[13px] font-semibold leading-[16px] text-[var(--text-primary)]", children: /* @__PURE__ */ jsx3(MentionSessionTitle, { item }) })
1092
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__session-title", children: /* @__PURE__ */ jsx5(MentionSessionTitle, { item }) })
822
1093
  ] }),
823
- item.statusTag ? /* @__PURE__ */ jsx3(
1094
+ item.statusTag ? /* @__PURE__ */ jsx5(
824
1095
  MentionStatusBadge,
825
1096
  {
826
1097
  statusTag: item.statusTag,
@@ -830,8 +1101,8 @@ function renderMentionRow(item, options) {
830
1101
  ] });
831
1102
  }
832
1103
  if (item.kind === "app") {
833
- return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-2 overflow-hidden", children: [
834
- /* @__PURE__ */ jsx3(
1104
+ return /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row rich-text-at-mention-row--app", children: [
1105
+ /* @__PURE__ */ jsx5(
835
1106
  MentionWorkspaceAppIcon,
836
1107
  {
837
1108
  iconUrl: item.iconUrl,
@@ -839,21 +1110,21 @@ function renderMentionRow(item, options) {
839
1110
  dataAttributeMode
840
1111
  }
841
1112
  ),
842
- /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 flex-1 items-baseline gap-1 overflow-hidden", children: [
843
- /* @__PURE__ */ jsx3("span", { className: "min-w-0 max-w-[40%] shrink-0 truncate text-[13px] font-semibold text-[var(--text-primary)]", children: item.name }),
844
- item.description ? /* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate text-[13px] font-normal text-[var(--text-secondary)]", children: item.description }) : null
1113
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__app-text", children: [
1114
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__app-name", children: item.name }),
1115
+ item.description ? /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__app-description", children: item.description }) : null
845
1116
  ] }),
846
1117
  referencesButton
847
1118
  ] });
848
1119
  }
849
1120
  if (item.kind === "app-factory") {
850
- return /* @__PURE__ */ jsx3("span", { className: "grid min-w-0 overflow-hidden gap-1", children: /* @__PURE__ */ jsx3("span", { className: "min-w-0 flex-1 truncate text-[13px] font-semibold text-[var(--text-primary)]", children: item.name }) });
1121
+ return /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__text-stack", children: /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__title", children: item.name }) });
851
1122
  }
852
- return /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-2 overflow-hidden", children: [
853
- /* @__PURE__ */ jsxs2("span", { className: "grid min-w-0 flex-1 overflow-hidden gap-1", children: [
854
- /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-center gap-2 overflow-hidden", children: [
855
- /* @__PURE__ */ jsx3("span", { className: "min-w-0 truncate text-[13px] font-semibold text-[var(--text-primary)]", children: item.title }),
856
- item.statusTag ? /* @__PURE__ */ jsx3(
1123
+ return /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row rich-text-at-mention-row--issue", children: [
1124
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__text-stack rich-text-at-mention-row__text-stack--fill", children: [
1125
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__inline", children: [
1126
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__title", children: item.title }),
1127
+ item.statusTag ? /* @__PURE__ */ jsx5(
857
1128
  MentionStatusBadge,
858
1129
  {
859
1130
  statusTag: item.statusTag,
@@ -861,7 +1132,7 @@ function renderMentionRow(item, options) {
861
1132
  }
862
1133
  ) : null
863
1134
  ] }),
864
- item.creatorName ? /* @__PURE__ */ jsx3("span", { className: "truncate text-[13px] font-normal text-[var(--text-secondary)]", children: item.creatorName }) : null
1135
+ item.creatorName ? /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__description", children: item.creatorName }) : null
865
1136
  ] }),
866
1137
  referencesButton
867
1138
  ] });
@@ -871,14 +1142,14 @@ function MentionOpenReferencesButton({
871
1142
  onOpenReferences,
872
1143
  dataAttributeMode
873
1144
  }) {
874
- return /* @__PURE__ */ jsx3(
1145
+ return /* @__PURE__ */ jsx5(
875
1146
  "span",
876
1147
  {
877
1148
  role: "button",
878
1149
  tabIndex: -1,
879
1150
  "aria-label": label,
880
1151
  title: label,
881
- className: "ml-auto grid h-6 w-6 shrink-0 cursor-pointer place-items-center rounded-[5px] text-[var(--text-tertiary)] transition-colors hover:bg-[var(--transparency-active)] hover:text-[var(--text-secondary)]",
1152
+ className: "rich-text-at-mention-row__open-references",
882
1153
  ...mentionRowDataAttribute(dataAttributeMode, "openReferences", "true"),
883
1154
  onMouseDown: (event) => {
884
1155
  event.preventDefault();
@@ -889,7 +1160,7 @@ function MentionOpenReferencesButton({
889
1160
  event.stopPropagation();
890
1161
  onOpenReferences();
891
1162
  },
892
- children: /* @__PURE__ */ jsx3(LocateFolderIcon, { size: 16 })
1163
+ children: /* @__PURE__ */ jsx5(LocateFolderIcon, { size: 16 })
893
1164
  }
894
1165
  );
895
1166
  }
@@ -898,10 +1169,10 @@ function MentionFileRow({
898
1169
  classNames,
899
1170
  dataAttributeMode
900
1171
  }) {
901
- return /* @__PURE__ */ jsxs2(
1172
+ return /* @__PURE__ */ jsxs3(
902
1173
  "span",
903
1174
  {
904
- className: "flex min-w-0 items-center gap-2",
1175
+ className: "rich-text-at-mention-row rich-text-at-mention-row--file",
905
1176
  ...mentionRowRootDataAttributes(dataAttributeMode, "file"),
906
1177
  ...item.entryKind ? mentionRowDataAttribute(
907
1178
  dataAttributeMode,
@@ -919,7 +1190,7 @@ function MentionFileRow({
919
1190
  item.mentionNavigation
920
1191
  ) : {},
921
1192
  children: [
922
- /* @__PURE__ */ jsx3(
1193
+ /* @__PURE__ */ jsx5(
923
1194
  MentionFileIcon,
924
1195
  {
925
1196
  item,
@@ -927,9 +1198,9 @@ function MentionFileRow({
927
1198
  dataAttributeMode
928
1199
  }
929
1200
  ),
930
- /* @__PURE__ */ jsxs2("span", { className: "flex min-w-0 items-baseline gap-1 overflow-hidden", children: [
931
- /* @__PURE__ */ jsx3("span", { className: "min-w-0 truncate text-[13px] font-semibold text-[var(--text-primary)]", children: item.name }),
932
- item.childCountLabel ? /* @__PURE__ */ jsx3("span", { className: "shrink-0 text-[13px] font-normal text-[var(--text-secondary)]", children: item.childCountLabel }) : null
1201
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__file-text", children: [
1202
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__title", children: item.name }),
1203
+ item.childCountLabel ? /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__file-count", children: item.childCountLabel }) : null
933
1204
  ] })
934
1205
  ]
935
1206
  }
@@ -942,18 +1213,18 @@ function MentionFileIcon({
942
1213
  }) {
943
1214
  const thumbnailUrl = item.visualKind === "image" ? item.thumbnailUrl?.trim() || "" : "";
944
1215
  if (thumbnailUrl) {
945
- return /* @__PURE__ */ jsx3(
1216
+ return /* @__PURE__ */ jsx5(
946
1217
  "span",
947
1218
  {
948
1219
  className: classNames.fileThumb,
949
1220
  ...mentionRowDataAttribute(dataAttributeMode, "fileThumb", "true"),
950
1221
  "aria-hidden": "true",
951
- children: /* @__PURE__ */ jsx3(
1222
+ children: /* @__PURE__ */ jsx5(
952
1223
  "img",
953
1224
  {
954
1225
  src: thumbnailUrl,
955
1226
  alt: "",
956
- className: "h-full w-full object-cover",
1227
+ className: "rich-text-at-mention-row__media",
957
1228
  decoding: "async",
958
1229
  loading: "lazy",
959
1230
  draggable: false
@@ -965,12 +1236,12 @@ function MentionFileIcon({
965
1236
  const usesDefaultFileIcon = classNames.fileIcon === DEFAULT_MENTION_ROW_CLASS_NAMES.fileIcon;
966
1237
  if (usesDefaultFileIcon) {
967
1238
  const Icon = MENTION_FILE_VISUAL_KIND_ICON[item.visualKind];
968
- return /* @__PURE__ */ jsx3(
1239
+ return /* @__PURE__ */ jsx5(
969
1240
  "span",
970
1241
  {
971
1242
  className: cn3(
972
1243
  classNames.fileIcon,
973
- "grid h-4 w-4 shrink-0 place-items-center text-[var(--text-secondary)]"
1244
+ "rich-text-at-mention-file-icon--glyph"
974
1245
  ),
975
1246
  ...mentionRowDataAttribute(
976
1247
  dataAttributeMode,
@@ -978,11 +1249,11 @@ function MentionFileIcon({
978
1249
  item.visualKind
979
1250
  ),
980
1251
  "aria-hidden": "true",
981
- children: /* @__PURE__ */ jsx3(Icon, { size: 16 })
1252
+ children: /* @__PURE__ */ jsx5(Icon, { size: 16 })
982
1253
  }
983
1254
  );
984
1255
  }
985
- return /* @__PURE__ */ jsx3(
1256
+ return /* @__PURE__ */ jsx5(
986
1257
  "span",
987
1258
  {
988
1259
  className: classNames.fileIcon,
@@ -1001,24 +1272,32 @@ function MentionWorkspaceAppIcon({
1001
1272
  dataAttributeMode
1002
1273
  }) {
1003
1274
  const normalizedIconUrl = iconUrl?.trim() ?? "";
1004
- return /* @__PURE__ */ jsx3(
1275
+ return /* @__PURE__ */ jsx5(
1005
1276
  "span",
1006
1277
  {
1007
- className: "grid h-5 w-5 shrink-0 place-items-center overflow-hidden rounded-[5px] bg-block text-[var(--text-secondary)]",
1278
+ className: "rich-text-at-mention-app-icon",
1008
1279
  ...mentionRowDataAttribute(dataAttributeMode, "appIcon", "true"),
1009
1280
  "data-workspace-app-icon": "true",
1010
1281
  "aria-hidden": "true",
1011
- children: normalizedIconUrl ? /* @__PURE__ */ jsx3(
1282
+ children: normalizedIconUrl ? /* @__PURE__ */ jsx5(
1012
1283
  "img",
1013
1284
  {
1014
1285
  src: normalizedIconUrl,
1015
1286
  alt: "",
1016
- className: "h-full w-full object-cover",
1287
+ className: "rich-text-at-mention-row__media",
1017
1288
  decoding: "async",
1018
1289
  loading: "lazy",
1019
1290
  draggable: false
1020
1291
  }
1021
- ) : /* @__PURE__ */ jsx3("span", { className: cn3(kindIconClassName, "h-4 w-4") })
1292
+ ) : /* @__PURE__ */ jsx5(
1293
+ "span",
1294
+ {
1295
+ className: cn3(
1296
+ kindIconClassName,
1297
+ "rich-text-at-mention-kind-icon--app"
1298
+ )
1299
+ }
1300
+ )
1022
1301
  }
1023
1302
  );
1024
1303
  }
@@ -1030,72 +1309,65 @@ function MentionSessionAvatarStack({
1030
1309
  const userAvatarUrl = item.userAvatarUrl?.trim() ?? "";
1031
1310
  const placeholderUrl = item.userAvatarPlaceholderUrl;
1032
1311
  const userImageUrl = userAvatarUrl || placeholderUrl;
1033
- return /* @__PURE__ */ jsxs2(
1034
- "span",
1035
- {
1036
- className: "relative isolate block h-5 w-9 shrink-0",
1037
- "aria-hidden": "true",
1038
- children: [
1039
- /* @__PURE__ */ jsx3(
1040
- "span",
1312
+ return /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-avatar-stack", "aria-hidden": "true", children: [
1313
+ /* @__PURE__ */ jsx5(
1314
+ "span",
1315
+ {
1316
+ className: "rich-text-at-mention-avatar rich-text-at-mention-avatar--user",
1317
+ ...mentionRowDataAttribute(dataAttributeMode, "userAvatar", "true"),
1318
+ children: /* @__PURE__ */ jsx5(
1319
+ "img",
1041
1320
  {
1042
- className: "absolute left-0 top-0 z-0 grid h-5 w-5 overflow-hidden rounded-full bg-block",
1043
- ...mentionRowDataAttribute(dataAttributeMode, "userAvatar", "true"),
1044
- children: /* @__PURE__ */ jsx3(
1045
- "img",
1046
- {
1047
- src: userImageUrl,
1048
- alt: "",
1049
- className: cn3(
1050
- "h-full w-full object-cover",
1051
- !userAvatarUrl && classNames.avatarImgUserPlaceholder
1052
- ),
1053
- decoding: "async",
1054
- loading: "lazy",
1055
- referrerPolicy: "no-referrer",
1056
- draggable: false,
1057
- onError: (event) => {
1058
- if (event.currentTarget.dataset.fallbackAvatarApplied === "true") {
1059
- return;
1060
- }
1061
- event.currentTarget.dataset.fallbackAvatarApplied = "true";
1062
- event.currentTarget.src = placeholderUrl;
1063
- event.currentTarget.classList.add(
1064
- classNames.avatarImgUserPlaceholder
1065
- );
1066
- }
1321
+ src: userImageUrl,
1322
+ alt: "",
1323
+ className: cn3(
1324
+ "rich-text-at-mention-row__media",
1325
+ !userAvatarUrl && classNames.avatarImgUserPlaceholder
1326
+ ),
1327
+ decoding: "async",
1328
+ loading: "lazy",
1329
+ referrerPolicy: "no-referrer",
1330
+ draggable: false,
1331
+ onError: (event) => {
1332
+ if (event.currentTarget.dataset.fallbackAvatarApplied === "true") {
1333
+ return;
1067
1334
  }
1068
- )
1335
+ event.currentTarget.dataset.fallbackAvatarApplied = "true";
1336
+ event.currentTarget.src = placeholderUrl;
1337
+ event.currentTarget.classList.add(
1338
+ classNames.avatarImgUserPlaceholder
1339
+ );
1340
+ }
1069
1341
  }
1070
- ),
1071
- /* @__PURE__ */ jsx3(
1072
- "span",
1342
+ )
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsx5(
1346
+ "span",
1347
+ {
1348
+ className: "rich-text-at-mention-avatar rich-text-at-mention-avatar--agent",
1349
+ ...mentionRowDataAttribute(dataAttributeMode, "agentAvatar", "true"),
1350
+ children: /* @__PURE__ */ jsx5(
1351
+ "img",
1073
1352
  {
1074
- className: "absolute left-4 top-0 z-10 grid h-5 w-5 overflow-hidden rounded-full bg-block",
1075
- ...mentionRowDataAttribute(dataAttributeMode, "agentAvatar", "true"),
1076
- children: /* @__PURE__ */ jsx3(
1077
- "img",
1078
- {
1079
- src: item.agentIconUrl,
1080
- alt: "",
1081
- className: "h-full w-full object-cover",
1082
- decoding: "async",
1083
- loading: "lazy",
1084
- draggable: false
1085
- }
1086
- )
1353
+ src: item.agentIconUrl,
1354
+ alt: "",
1355
+ className: "rich-text-at-mention-row__media",
1356
+ decoding: "async",
1357
+ loading: "lazy",
1358
+ draggable: false
1087
1359
  }
1088
1360
  )
1089
- ]
1090
- }
1091
- );
1361
+ }
1362
+ )
1363
+ ] });
1092
1364
  }
1093
1365
  function MentionSessionTitle({
1094
1366
  item
1095
1367
  }) {
1096
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
1097
- /* @__PURE__ */ jsx3("span", { className: "text-[13px] leading-[16px]", children: item.participant }),
1098
- /* @__PURE__ */ jsxs2("span", { className: "text-[13px] font-normal leading-[16px] text-[var(--text-secondary)]", children: [
1368
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
1369
+ /* @__PURE__ */ jsx5("span", { className: "rich-text-at-mention-row__session-participant", children: item.participant }),
1370
+ /* @__PURE__ */ jsxs3("span", { className: "rich-text-at-mention-row__session-summary", children: [
1099
1371
  " ",
1100
1372
  item.summary ?? ""
1101
1373
  ] })
@@ -1106,12 +1378,12 @@ function MentionStatusBadge({
1106
1378
  dataAttributeMode
1107
1379
  }) {
1108
1380
  if (statusTag.variant === "issue") {
1109
- return /* @__PURE__ */ jsx3(
1381
+ return /* @__PURE__ */ jsx5(
1110
1382
  Badge,
1111
1383
  {
1112
1384
  variant: "secondary",
1113
1385
  className: cn3(
1114
- "shrink-0 text-[13px]",
1386
+ "rich-text-at-mention-status rich-text-at-mention-status--issue",
1115
1387
  mentionStatusBadgeClassName({
1116
1388
  tone: statusTag.tone,
1117
1389
  variant: "issue"
@@ -1119,16 +1391,17 @@ function MentionStatusBadge({
1119
1391
  ),
1120
1392
  ...mentionRowDataAttribute(dataAttributeMode, "statusTag", "true"),
1121
1393
  ...statusTag.dataStatus ? { "data-status": statusTag.dataStatus } : {},
1394
+ "data-tone": statusTag.tone,
1122
1395
  children: statusTag.label
1123
1396
  }
1124
1397
  );
1125
1398
  }
1126
- return /* @__PURE__ */ jsxs2(
1399
+ return /* @__PURE__ */ jsxs3(
1127
1400
  Badge,
1128
1401
  {
1129
1402
  variant: "secondary",
1130
1403
  className: cn3(
1131
- "inline-flex h-5 shrink-0 items-center gap-1.5 rounded-[4px] px-2 text-[11px] font-semibold leading-none",
1404
+ "rich-text-at-mention-status rich-text-at-mention-status--activity",
1132
1405
  mentionStatusBadgeClassName({
1133
1406
  tone: statusTag.tone,
1134
1407
  variant: "activity"
@@ -1139,7 +1412,7 @@ function MentionStatusBadge({
1139
1412
  "data-tone": statusTag.tone,
1140
1413
  title: statusTag.label,
1141
1414
  children: [
1142
- /* @__PURE__ */ jsx3(
1415
+ /* @__PURE__ */ jsx5(
1143
1416
  StatusDot,
1144
1417
  {
1145
1418
  tone: statusTag.tone,
@@ -1148,12 +1421,466 @@ function MentionStatusBadge({
1148
1421
  title: statusTag.label
1149
1422
  }
1150
1423
  ),
1151
- /* @__PURE__ */ jsx3("span", { children: statusTag.label })
1424
+ /* @__PURE__ */ jsx5("span", { children: statusTag.label })
1152
1425
  ]
1153
1426
  }
1154
1427
  );
1155
1428
  }
1156
1429
 
1430
+ // src/at-panel/mentionReferenceIcon.ts
1431
+ import React from "react";
1432
+ var REFERENCE_LEADING_STYLE = {
1433
+ alignItems: "center",
1434
+ background: "var(--bg-block, var(--block, #0000000a))",
1435
+ borderRadius: "8px",
1436
+ color: "var(--rich-text-at-mention-text-secondary, currentColor)",
1437
+ display: "inline-grid",
1438
+ flex: "0 0 32px",
1439
+ height: "32px",
1440
+ justifyItems: "center",
1441
+ overflow: "hidden",
1442
+ width: "32px"
1443
+ };
1444
+ var REFERENCE_IMAGE_STYLE = {
1445
+ display: "block",
1446
+ height: "100%",
1447
+ objectFit: "cover",
1448
+ width: "100%"
1449
+ };
1450
+ var REFERENCE_ICON_STYLE = {
1451
+ display: "block",
1452
+ height: "18px",
1453
+ width: "18px"
1454
+ };
1455
+ function resolveMentionReferenceImageUrl(input) {
1456
+ return input.thumbnailUrl?.trim() || input.iconUrl?.trim() || void 0;
1457
+ }
1458
+ function renderMentionReferenceLeading(input) {
1459
+ const imageUrl = resolveMentionReferenceImageUrl(input);
1460
+ return React.createElement(
1461
+ "span",
1462
+ {
1463
+ "aria-hidden": "true",
1464
+ className: input.className,
1465
+ "data-rich-text-at-mention-reference-kind": input.kind,
1466
+ "data-rich-text-at-mention-reference-leading": "true",
1467
+ style: REFERENCE_LEADING_STYLE
1468
+ },
1469
+ imageUrl ? React.createElement("img", {
1470
+ alt: "",
1471
+ className: input.imageClassName,
1472
+ decoding: "async",
1473
+ draggable: false,
1474
+ loading: "lazy",
1475
+ src: imageUrl,
1476
+ style: REFERENCE_IMAGE_STYLE
1477
+ }) : renderMentionReferenceFallbackIcon(input)
1478
+ );
1479
+ }
1480
+ function renderMentionReferenceFallbackIcon(input) {
1481
+ return React.createElement(
1482
+ "svg",
1483
+ {
1484
+ "aria-hidden": "true",
1485
+ fill: "none",
1486
+ stroke: "currentColor",
1487
+ strokeLinecap: "round",
1488
+ strokeLinejoin: "round",
1489
+ strokeWidth: 1.8,
1490
+ style: REFERENCE_ICON_STYLE,
1491
+ viewBox: "0 0 24 24"
1492
+ },
1493
+ ...referenceIconPaths(input)
1494
+ );
1495
+ }
1496
+ function referenceIconPaths(input) {
1497
+ if (input.kind === "workspace-app") {
1498
+ return [
1499
+ React.createElement("rect", {
1500
+ height: 7,
1501
+ key: "a",
1502
+ rx: 1.5,
1503
+ width: 7,
1504
+ x: 4,
1505
+ y: 4
1506
+ }),
1507
+ React.createElement("rect", {
1508
+ height: 7,
1509
+ key: "b",
1510
+ rx: 1.5,
1511
+ width: 7,
1512
+ x: 13,
1513
+ y: 4
1514
+ }),
1515
+ React.createElement("rect", {
1516
+ height: 7,
1517
+ key: "c",
1518
+ rx: 1.5,
1519
+ width: 7,
1520
+ x: 4,
1521
+ y: 13
1522
+ }),
1523
+ React.createElement("rect", {
1524
+ height: 7,
1525
+ key: "d",
1526
+ rx: 1.5,
1527
+ width: 7,
1528
+ x: 13,
1529
+ y: 13
1530
+ })
1531
+ ];
1532
+ }
1533
+ if (input.kind === "workspace-issue") {
1534
+ return [
1535
+ React.createElement("circle", { cx: 12, cy: 12, key: "a", r: 8 }),
1536
+ React.createElement("path", { d: "M8.5 12.5 11 15l4.5-5", key: "b" })
1537
+ ];
1538
+ }
1539
+ if (input.kind === "agent-session") {
1540
+ return [
1541
+ React.createElement("path", {
1542
+ d: "M6 9.5a5 5 0 0 1 5-5h2a5 5 0 0 1 5 5v2.5a5 5 0 0 1-5 5h-1.5L8 19v-2.4A5 5 0 0 1 6 12z",
1543
+ key: "a"
1544
+ })
1545
+ ];
1546
+ }
1547
+ if (input.kind === "file" || input.kind === "agent-generated-file" || input.fileVisualKind != null) {
1548
+ if (input.fileVisualKind === "folder" || input.fileVisualKind === "back") {
1549
+ return [
1550
+ React.createElement("path", {
1551
+ d: "M3.5 7.5h6l2 2h9v8a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z",
1552
+ key: "a"
1553
+ })
1554
+ ];
1555
+ }
1556
+ if (input.fileVisualKind === "image") {
1557
+ return [
1558
+ React.createElement("rect", {
1559
+ height: 14,
1560
+ key: "a",
1561
+ rx: 2,
1562
+ width: 16,
1563
+ x: 4,
1564
+ y: 5
1565
+ }),
1566
+ React.createElement("path", {
1567
+ d: "m7 16 3.5-3.5 2.5 2.5 2-2 2 3",
1568
+ key: "b"
1569
+ }),
1570
+ React.createElement("circle", { cx: 9, cy: 9, key: "c", r: 1 })
1571
+ ];
1572
+ }
1573
+ if (input.fileVisualKind === "video") {
1574
+ return [
1575
+ React.createElement("rect", {
1576
+ height: 14,
1577
+ key: "a",
1578
+ rx: 2,
1579
+ width: 16,
1580
+ x: 4,
1581
+ y: 5
1582
+ }),
1583
+ React.createElement("path", {
1584
+ d: "m10 9 5 3-5 3z",
1585
+ key: "b"
1586
+ })
1587
+ ];
1588
+ }
1589
+ return [
1590
+ React.createElement("path", {
1591
+ d: "M7 3.5h7l4 4V20a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V4.5a1 1 0 0 1 1-1z",
1592
+ key: "a"
1593
+ }),
1594
+ React.createElement("path", { d: "M14 3.5v4h4", key: "b" })
1595
+ ];
1596
+ }
1597
+ return [
1598
+ React.createElement("path", {
1599
+ d: "M9.5 14.5 14.5 9.5",
1600
+ key: "a"
1601
+ }),
1602
+ React.createElement("path", {
1603
+ d: "M8.5 10.5 7 12a3.5 3.5 0 0 0 5 5l1.5-1.5",
1604
+ key: "b"
1605
+ }),
1606
+ React.createElement("path", {
1607
+ d: "M15.5 13.5 17 12a3.5 3.5 0 0 0-5-5l-1.5 1.5",
1608
+ key: "c"
1609
+ })
1610
+ ];
1611
+ }
1612
+
1613
+ // src/at-panel/mentionTriggerRowItem.ts
1614
+ var SUPPORTED_MENTION_TRIGGER_ROW_PROVIDER_IDS = /* @__PURE__ */ new Set([
1615
+ "agent-generated-file",
1616
+ "agent-session",
1617
+ "file",
1618
+ "workspace-app",
1619
+ "workspace-issue"
1620
+ ]);
1621
+ function richTextTriggerQueryMatchToMentionRowItem(match, options = {}) {
1622
+ const presentation = mentionPresentation(match);
1623
+ const label = resolveMentionRowLabel(match);
1624
+ const description = resolveMentionRowDescription(match, options);
1625
+ const providerKind = mentionReferenceProviderKind(match.providerId);
1626
+ const iconUrl = resolveMentionRowIconUrl(match, presentation, options);
1627
+ const thumbnailUrl = resolveMentionRowThumbnailUrl(
1628
+ match,
1629
+ presentation,
1630
+ options
1631
+ );
1632
+ const fileVisualKind = isFileMentionProvider(match.providerId) ? resolveMentionRowFileVisualKind(match, options) : void 0;
1633
+ const customLeading = options.renderLeading?.({
1634
+ description,
1635
+ fileVisualKind,
1636
+ iconUrl,
1637
+ label,
1638
+ match,
1639
+ providerKind,
1640
+ thumbnailUrl
1641
+ });
1642
+ if (customLeading !== void 0) {
1643
+ return mentionRowPlainItem({
1644
+ description,
1645
+ label,
1646
+ leading: customLeading
1647
+ });
1648
+ }
1649
+ if (match.providerId === "workspace-app") {
1650
+ return {
1651
+ kind: "app",
1652
+ description,
1653
+ iconUrl,
1654
+ name: label
1655
+ };
1656
+ }
1657
+ if (match.providerId === "workspace-issue") {
1658
+ return {
1659
+ kind: "issue",
1660
+ creatorName: description,
1661
+ statusTag: resolveMentionRowStatusTag(match, "issue", options),
1662
+ title: label
1663
+ };
1664
+ }
1665
+ if (isFileMentionProvider(match.providerId)) {
1666
+ const entryKind = resolveFileEntryKind(match, options);
1667
+ const mentionNavigation = resolveFileMentionNavigation(match, options);
1668
+ const visualKind = fileVisualKind ?? "document";
1669
+ return {
1670
+ kind: "file",
1671
+ childCountLabel: normalizedText(options.getChildCountLabel?.(match)),
1672
+ entryKind,
1673
+ mentionNavigation,
1674
+ name: label,
1675
+ thumbnailUrl: resolveMentionFileThumbnailUrl({
1676
+ thumbnailUrl,
1677
+ visualKind
1678
+ }) ?? null,
1679
+ visualKind
1680
+ };
1681
+ }
1682
+ if (match.providerId === "agent-session") {
1683
+ const session = agentSessionMentionRowItem(match, {
1684
+ description,
1685
+ iconUrl,
1686
+ options,
1687
+ presentation
1688
+ });
1689
+ if (session) {
1690
+ return session;
1691
+ }
1692
+ }
1693
+ return mentionRowPlainItem({
1694
+ description,
1695
+ label,
1696
+ leading: renderMentionReferenceLeading({
1697
+ fileVisualKind,
1698
+ iconUrl,
1699
+ kind: providerKind,
1700
+ label,
1701
+ thumbnailUrl
1702
+ })
1703
+ });
1704
+ }
1705
+ function isMentionTriggerRowProviderId(providerId) {
1706
+ return SUPPORTED_MENTION_TRIGGER_ROW_PROVIDER_IDS.has(providerId);
1707
+ }
1708
+ function workspaceAppIconFallbackUrlFromTriggerMatch(match) {
1709
+ const appId = mentionEntityId(match) || match.key.trim();
1710
+ if (!appId) {
1711
+ return null;
1712
+ }
1713
+ return `tutti://workspace-apps/${encodeURIComponent(appId)}/icon.png`;
1714
+ }
1715
+ function mentionRowStatusTagFromPresentation(match, input) {
1716
+ const presentation = mentionPresentation(match);
1717
+ const label = normalizedText(presentation?.statusLabel);
1718
+ if (!label) {
1719
+ return null;
1720
+ }
1721
+ const dataStatus = normalizedText(presentation?.statusDataStatus) ?? normalizedText(presentation?.status);
1722
+ return {
1723
+ dataStatus: dataStatus ?? void 0,
1724
+ label,
1725
+ pulse: presentation?.statusPulse === "true",
1726
+ tone: input.tone ?? "neutral",
1727
+ variant: input.variant
1728
+ };
1729
+ }
1730
+ function agentSessionMentionRowItem(match, input) {
1731
+ const agentIconUrl = normalizedText(input.options.getAgentIconUrl?.(match)) ?? normalizedText(input.presentation?.agentIconUrl) ?? input.iconUrl;
1732
+ const userAvatarPlaceholderUrl = normalizedText(input.options.getUserAvatarPlaceholderUrl?.(match)) ?? normalizedText(input.presentation?.userAvatarPlaceholderUrl);
1733
+ if (!agentIconUrl || !userAvatarPlaceholderUrl) {
1734
+ return null;
1735
+ }
1736
+ return {
1737
+ kind: "session",
1738
+ agentIconUrl,
1739
+ participant: normalizedText(input.presentation?.participant) ?? resolveMentionRowLabel(match),
1740
+ statusTag: resolveMentionRowStatusTag(match, "activity", input.options),
1741
+ summary: input.description,
1742
+ userAvatarPlaceholderUrl,
1743
+ userAvatarUrl: normalizedText(input.options.getUserAvatarUrl?.(match)) ?? null
1744
+ };
1745
+ }
1746
+ function mentionRowPlainItem(input) {
1747
+ return {
1748
+ kind: "plain",
1749
+ description: input.description,
1750
+ label: input.label,
1751
+ leading: input.leading
1752
+ };
1753
+ }
1754
+ function resolveMentionRowLabel(match) {
1755
+ return normalizedText(
1756
+ match.insertResult.kind === "mention" ? match.insertResult.mention.label : match.insertResult.kind === "markdown-link" ? match.insertResult.label : void 0
1757
+ ) ?? normalizedText(match.label) ?? match.key;
1758
+ }
1759
+ function resolveMentionRowDescription(match, options) {
1760
+ const presentation = mentionPresentation(match);
1761
+ return normalizedText(options.getDescription?.(match)) ?? normalizedText(presentation?.description) ?? normalizedText(presentation?.subtitle) ?? normalizedText(match.subtitle) ?? null;
1762
+ }
1763
+ function resolveMentionRowIconUrl(match, presentation, options) {
1764
+ return normalizedText(presentation?.iconUrl) ?? normalizedText(match.iconUrl) ?? (match.providerId === "workspace-app" ? normalizedText(options.getWorkspaceAppIconFallbackUrl?.(match)) ?? workspaceAppIconFallbackUrlFromTriggerMatch(match) : null) ?? null;
1765
+ }
1766
+ function resolveMentionRowThumbnailUrl(match, presentation, options) {
1767
+ return normalizedText(options.getFileThumbnailUrl?.(match)) ?? normalizedText(presentation?.thumbnailUrl) ?? normalizedText(readStringProperty(match.item, "thumbnailUrl")) ?? (isFileMentionProvider(match.providerId) ? normalizedText(match.iconUrl) : null) ?? null;
1768
+ }
1769
+ function resolveMentionRowFileVisualKind(match, options) {
1770
+ const override = options.getFileVisualKind?.(match);
1771
+ if (override) {
1772
+ return override;
1773
+ }
1774
+ return resolveMentionFileVisualKind({
1775
+ baseVisualKind: inferMentionFileVisualKind(
1776
+ markdownLinkHref(match) ?? normalizedText(match.subtitle) ?? normalizedText(match.label) ?? match.key
1777
+ ),
1778
+ entryKind: resolveFileEntryKind(match, options),
1779
+ mentionNavigation: resolveFileMentionNavigation(match, options)
1780
+ });
1781
+ }
1782
+ function resolveMentionRowStatusTag(match, variant, options) {
1783
+ return options.getStatusTag?.(match, variant) ?? mentionRowStatusTagFromPresentation(match, { variant });
1784
+ }
1785
+ function resolveFileEntryKind(match, options) {
1786
+ return normalizedText(options.getFileEntryKind?.(match)) ?? normalizedText(readStringProperty(match.item, "entryKind")) ?? normalizedText(readStringProperty(match.item, "kind")) ?? null;
1787
+ }
1788
+ function resolveFileMentionNavigation(match, options) {
1789
+ return normalizedText(options.getFileMentionNavigation?.(match)) ?? normalizedText(readStringProperty(match.item, "mentionNavigation")) ?? null;
1790
+ }
1791
+ function mentionReferenceProviderKind(providerId) {
1792
+ if (providerId === "workspace-app") {
1793
+ return "workspace-app";
1794
+ }
1795
+ if (providerId === "workspace-issue") {
1796
+ return "workspace-issue";
1797
+ }
1798
+ if (providerId === "agent-session") {
1799
+ return "agent-session";
1800
+ }
1801
+ if (providerId === "agent-generated-file") {
1802
+ return "agent-generated-file";
1803
+ }
1804
+ if (providerId === "file") {
1805
+ return "file";
1806
+ }
1807
+ return "generic";
1808
+ }
1809
+ function isFileMentionProvider(providerId) {
1810
+ return providerId === "file" || providerId === "agent-generated-file";
1811
+ }
1812
+ function mentionPresentation(match) {
1813
+ return match.insertResult.kind === "mention" ? match.insertResult.mention.presentation ?? null : null;
1814
+ }
1815
+ function mentionEntityId(match) {
1816
+ return match.insertResult.kind === "mention" ? normalizedText(match.insertResult.mention.entityId) ?? null : null;
1817
+ }
1818
+ function markdownLinkHref(match) {
1819
+ return match.insertResult.kind === "markdown-link" ? normalizedText(match.insertResult.href) ?? null : null;
1820
+ }
1821
+ function inferMentionFileVisualKind(pathOrName) {
1822
+ const normalized = pathOrName.trim().toLowerCase();
1823
+ if (!normalized) {
1824
+ return "document";
1825
+ }
1826
+ if (normalized.endsWith("/")) {
1827
+ return "folder";
1828
+ }
1829
+ const extension = normalized.match(/\.([a-z0-9]+)(?:[?#].*)?$/)?.[1] ?? "";
1830
+ if (["apng", "avif", "gif", "jpeg", "jpg", "png", "svg", "webp"].includes(
1831
+ extension
1832
+ )) {
1833
+ return "image";
1834
+ }
1835
+ if (["avi", "m4v", "mkv", "mov", "mp4", "webm"].includes(extension)) {
1836
+ return "video";
1837
+ }
1838
+ if (["markdown", "md", "mdx"].includes(extension)) {
1839
+ return "markdown";
1840
+ }
1841
+ if ([
1842
+ "c",
1843
+ "cpp",
1844
+ "css",
1845
+ "go",
1846
+ "h",
1847
+ "hpp",
1848
+ "html",
1849
+ "java",
1850
+ "js",
1851
+ "jsx",
1852
+ "json",
1853
+ "kt",
1854
+ "php",
1855
+ "py",
1856
+ "rb",
1857
+ "rs",
1858
+ "sh",
1859
+ "sql",
1860
+ "swift",
1861
+ "toml",
1862
+ "ts",
1863
+ "tsx",
1864
+ "xml",
1865
+ "yaml",
1866
+ "yml"
1867
+ ].includes(extension)) {
1868
+ return "code";
1869
+ }
1870
+ return "document";
1871
+ }
1872
+ function readStringProperty(value, key) {
1873
+ if (value === null || typeof value !== "object") {
1874
+ return void 0;
1875
+ }
1876
+ const record = value;
1877
+ return typeof record[key] === "string" ? record[key] : void 0;
1878
+ }
1879
+ function normalizedText(value) {
1880
+ const normalized = value?.trim() ?? "";
1881
+ return normalized || null;
1882
+ }
1883
+
1157
1884
  // src/at-panel/useAtPanelKeyboard.ts
1158
1885
  function makeAtPanelKeyDown(actions) {
1159
1886
  return (event) => {
@@ -1177,6 +1904,16 @@ function makeAtPanelKeyDown(actions) {
1177
1904
  actions.cycleFilter(event.shiftKey ? -1 : 1);
1178
1905
  return true;
1179
1906
  }
1907
+ if (event.key === "ArrowRight" && actions.cycleFilter) {
1908
+ event.preventDefault();
1909
+ actions.cycleFilter(1);
1910
+ return true;
1911
+ }
1912
+ if (event.key === "ArrowLeft" && actions.cycleFilter) {
1913
+ event.preventDefault();
1914
+ actions.cycleFilter(-1);
1915
+ return true;
1916
+ }
1180
1917
  if (event.key === "Enter") {
1181
1918
  event.preventDefault();
1182
1919
  actions.commitSelection();
@@ -1189,26 +1926,35 @@ function useAtPanelKeyboard(actions) {
1189
1926
  return makeAtPanelKeyDown(actions);
1190
1927
  }
1191
1928
  export {
1192
- DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE,
1193
1929
  MentionPalette,
1194
- RICH_TEXT_AT_ALL_FILTER_ID,
1930
+ MentionPaletteFromState,
1931
+ MentionPaletteMultiSelectFooter,
1932
+ MentionPaletteSelectIndicator,
1195
1933
  activityMentionStatusBadgeClassName,
1196
1934
  activityMentionStatusTone,
1197
- buildDefaultRichTextTriggerProviderGroups,
1198
- buildMentionPaletteState,
1199
- buildRichTextAtFilterTabs,
1200
- findRichTextTriggerProviderGroup,
1935
+ buildMentionPaletteModel,
1936
+ buildMentionPaletteModelFromTriggerMatches,
1937
+ createMentionPaletteStateAdapter,
1938
+ findMentionPaletteEntry,
1201
1939
  flattenMentionPaletteEntries,
1202
- groupRichTextAtMatches,
1940
+ isMentionTriggerRowProviderId,
1203
1941
  issueMentionStatusBadgeClassName,
1204
1942
  issueMentionStatusTone,
1205
1943
  makeAtPanelKeyDown,
1944
+ mentionPaletteGroup,
1945
+ mentionRowStatusTagFromPresentation,
1206
1946
  mentionStatusBadgeClassName,
1207
- normalizeAtPanelQuery,
1947
+ moveMentionPaletteHighlight,
1948
+ nextMentionPaletteCategory,
1949
+ renderMentionReferenceLeading,
1208
1950
  renderMentionRow,
1951
+ repairMentionPaletteHighlight,
1209
1952
  resolveMentionFileThumbnailUrl,
1210
1953
  resolveMentionFileVisualKind,
1211
- richTextAtGroupExpandCount,
1212
- useAtPanelKeyboard
1954
+ resolveMentionReferenceImageUrl,
1955
+ richTextTriggerQueryMatchToMentionRowItem,
1956
+ selectedMentionPaletteItem,
1957
+ useAtPanelKeyboard,
1958
+ workspaceAppIconFallbackUrlFromTriggerMatch
1213
1959
  };
1214
1960
  //# sourceMappingURL=index.js.map