@ai-matrx/associations 0.11.3 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-4DN5Fe4g.cjs';
4
- export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-4DN5Fe4g.cjs';
3
+ import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-C78e8433.cjs';
4
+ export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-C78e8433.cjs';
5
5
 
6
6
  interface AssociationsUiPorts {
7
7
  notifier?: AssociationsNotifier;
@@ -104,16 +104,25 @@ interface UseUniversalEntitySearchArgs {
104
104
  /**
105
105
  * What an empty query loads. Universal attach surfaces default to recents;
106
106
  * constrained value pickers use candidates so opening the picker immediately
107
- * shows the records that are available to select.
107
+ * shows the records that are available to select. `"recents"` falls back
108
+ * to candidates when the person has no recents for the searched tokens.
108
109
  */
109
110
  emptyQueryMode?: "recents" | "candidates";
110
111
  }
112
+ /**
113
+ * What the current results ARE: `"search"` for a typed query, `"recents"` for
114
+ * favorites/last-viewed, `"candidates"` for an empty-query browse (asked for,
115
+ * or the recents fallback).
116
+ */
117
+ type UniversalSearchSource = "search" | "recents" | "candidates";
111
118
  interface UseUniversalEntitySearchReturn {
112
119
  results: UniversalCandidate[];
113
120
  /** True while the current query's sweep is in flight. */
114
121
  loading: boolean;
115
122
  /** True when `results` are recents (empty query), not search hits. */
116
123
  isRecents: boolean;
124
+ /** What the results are — lets the face label a browse vs recents vs hits. */
125
+ source: UniversalSearchSource;
117
126
  }
118
127
  declare function useUniversalEntitySearch(args: UseUniversalEntitySearchArgs): UseUniversalEntitySearchReturn;
119
128
 
@@ -295,4 +304,4 @@ interface ContentRoleMeta {
295
304
  declare const CONTENT_ROLES: ContentRoleMeta[];
296
305
  declare function getContentRoleMeta(role: ContentRole): ContentRoleMeta;
297
306
 
298
- export { AssociationCandidateBody, type AssociationCandidateBodyProps, AssociationPicker, type AssociationPickerBridge, type AssociationPickerBridgeOptions, AssociationPickerProps, AssociationsProvider, type AssociationsProviderProps, type AssociationsUiPorts, CONTENT_ROLES, CandidateRecord, type CategoryCreateResult, CategoryMutationResult, type ContentRoleMeta, DefaultWindowShell, type DefaultWindowShellProps, DoorControlsSlot, DoorRef, type EntityTitleRef, type PickerBridgeItem, UniversalCandidate, UnresolvedRef, type UseAssociationCandidatesArgs, type UseAssociationCandidatesReturn, type UseCategoriesArgs, type UseCategoriesReturn, type UseCommentsArgs, type UseCommentsReturn, type UseEntityTitlesReturn, type UseUniversalEntitySearchArgs, type UseUniversalEntitySearchReturn, type WindowShellComponentProps, getContentRoleMeta, lazyPickerOverride, lazyWindowShell, useAssociationCandidates, useAssociationPickerBridge, useAssociationsStore, useAssociationsUiPorts, useCategories, useComments, useEntityTitles, useNotifier, useUniversalEntitySearch };
307
+ export { AssociationCandidateBody, type AssociationCandidateBodyProps, AssociationPicker, type AssociationPickerBridge, type AssociationPickerBridgeOptions, AssociationPickerProps, AssociationsProvider, type AssociationsProviderProps, type AssociationsUiPorts, CONTENT_ROLES, CandidateRecord, type CategoryCreateResult, CategoryMutationResult, type ContentRoleMeta, DefaultWindowShell, type DefaultWindowShellProps, DoorControlsSlot, DoorRef, type EntityTitleRef, type PickerBridgeItem, UniversalCandidate, type UniversalSearchSource, UnresolvedRef, type UseAssociationCandidatesArgs, type UseAssociationCandidatesReturn, type UseCategoriesArgs, type UseCategoriesReturn, type UseCommentsArgs, type UseCommentsReturn, type UseEntityTitlesReturn, type UseUniversalEntitySearchArgs, type UseUniversalEntitySearchReturn, type WindowShellComponentProps, getContentRoleMeta, lazyPickerOverride, lazyWindowShell, useAssociationCandidates, useAssociationPickerBridge, useAssociationsStore, useAssociationsUiPorts, useCategories, useComments, useEntityTitles, useNotifier, useUniversalEntitySearch };
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ComponentType } from 'react';
3
- import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-4DN5Fe4g.js';
4
- export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-4DN5Fe4g.js';
3
+ import { j as AssociationsNotifier, W as WindowShellPort, k as CapturePort, P as PickerOverrideMap, E as EntityDoorsPort, l as AuthorDisplayPort, m as AssociationsStore, n as CategoryMutationResult, o as CategoryDimension, p as PlatformCategory, q as CategoriesEntry, r as EntityTypeToken, s as UniversalCandidate, t as CandidateRecord, u as PlatformComment, v as CommentsEntry, w as CommentMutationResult, e as AssociationPickerProps, x as EntityDoorProps, y as EntityRefProps, z as ContentRole } from '../CommentThread-C78e8433.js';
4
+ export { B as AssociationCaptureToolbar, A as AssociationCaptureToolbarProps, D as AssociationCard, F as AssociationCardGrid, b as AssociationCardGridProps, a as AssociationCardProps, G as AssociationEntitySelect, H as AssociationEntitySelectAdapter, I as AssociationEntitySelectItem, c as AssociationEntitySelectProps, J as AssociationList, d as AssociationListProps, K as AssociationWindow, f as AssociationWindowProps, L as AssociationWriteResult, M as AttachedItemsSheet, g as AttachedItemsSheetProps, N as CaptureAttach, O as CaptureAttachResult, Q as CaptureToolbarAction, R as CategorySelect, C as CategorySelectProps, S as CategoryTagPicker, h as CategoryTagPickerProps, T as CommentComposer, V as CommentComposerProps, X as CommentThread, i as CommentThreadProps, Y as ContainerLink, Z as ContainerResourceRow, _ as ContainerResourcesAdapter, $ as DefaultEntityIcon, a0 as PrimaryContainerEntity, a1 as PrimaryEntity, a2 as PrimaryEntityProvider, a3 as PrimaryFiledEntity, a4 as TagPickerIcon, a5 as UniversalAssociationPicker, U as UniversalAssociationPickerProps, a6 as UseAssociationEntitySelectAdapterArgs, a7 as UseAssociationsArgs, a8 as UseAssociationsReturn, a9 as UseContainerLinksArgs, aa as UseContainerLinksReturn, ab as attachedKey, ac as buildCommentTree, ad as containerLinksArgs, ae as useAssociationEntitySelectAdapter, af as useAssociations, ag as useContainerLinks, ah as useContainerLinksAdapter, ai as useEntityRelationships, aj as usePrimaryEntity } from '../CommentThread-C78e8433.js';
5
5
 
6
6
  interface AssociationsUiPorts {
7
7
  notifier?: AssociationsNotifier;
@@ -104,16 +104,25 @@ interface UseUniversalEntitySearchArgs {
104
104
  /**
105
105
  * What an empty query loads. Universal attach surfaces default to recents;
106
106
  * constrained value pickers use candidates so opening the picker immediately
107
- * shows the records that are available to select.
107
+ * shows the records that are available to select. `"recents"` falls back
108
+ * to candidates when the person has no recents for the searched tokens.
108
109
  */
109
110
  emptyQueryMode?: "recents" | "candidates";
110
111
  }
112
+ /**
113
+ * What the current results ARE: `"search"` for a typed query, `"recents"` for
114
+ * favorites/last-viewed, `"candidates"` for an empty-query browse (asked for,
115
+ * or the recents fallback).
116
+ */
117
+ type UniversalSearchSource = "search" | "recents" | "candidates";
111
118
  interface UseUniversalEntitySearchReturn {
112
119
  results: UniversalCandidate[];
113
120
  /** True while the current query's sweep is in flight. */
114
121
  loading: boolean;
115
122
  /** True when `results` are recents (empty query), not search hits. */
116
123
  isRecents: boolean;
124
+ /** What the results are — lets the face label a browse vs recents vs hits. */
125
+ source: UniversalSearchSource;
117
126
  }
118
127
  declare function useUniversalEntitySearch(args: UseUniversalEntitySearchArgs): UseUniversalEntitySearchReturn;
119
128
 
@@ -295,4 +304,4 @@ interface ContentRoleMeta {
295
304
  declare const CONTENT_ROLES: ContentRoleMeta[];
296
305
  declare function getContentRoleMeta(role: ContentRole): ContentRoleMeta;
297
306
 
298
- export { AssociationCandidateBody, type AssociationCandidateBodyProps, AssociationPicker, type AssociationPickerBridge, type AssociationPickerBridgeOptions, AssociationPickerProps, AssociationsProvider, type AssociationsProviderProps, type AssociationsUiPorts, CONTENT_ROLES, CandidateRecord, type CategoryCreateResult, CategoryMutationResult, type ContentRoleMeta, DefaultWindowShell, type DefaultWindowShellProps, DoorControlsSlot, DoorRef, type EntityTitleRef, type PickerBridgeItem, UniversalCandidate, UnresolvedRef, type UseAssociationCandidatesArgs, type UseAssociationCandidatesReturn, type UseCategoriesArgs, type UseCategoriesReturn, type UseCommentsArgs, type UseCommentsReturn, type UseEntityTitlesReturn, type UseUniversalEntitySearchArgs, type UseUniversalEntitySearchReturn, type WindowShellComponentProps, getContentRoleMeta, lazyPickerOverride, lazyWindowShell, useAssociationCandidates, useAssociationPickerBridge, useAssociationsStore, useAssociationsUiPorts, useCategories, useComments, useEntityTitles, useNotifier, useUniversalEntitySearch };
307
+ export { AssociationCandidateBody, type AssociationCandidateBodyProps, AssociationPicker, type AssociationPickerBridge, type AssociationPickerBridgeOptions, AssociationPickerProps, AssociationsProvider, type AssociationsProviderProps, type AssociationsUiPorts, CONTENT_ROLES, CandidateRecord, type CategoryCreateResult, CategoryMutationResult, type ContentRoleMeta, DefaultWindowShell, type DefaultWindowShellProps, DoorControlsSlot, DoorRef, type EntityTitleRef, type PickerBridgeItem, UniversalCandidate, type UniversalSearchSource, UnresolvedRef, type UseAssociationCandidatesArgs, type UseAssociationCandidatesReturn, type UseCategoriesArgs, type UseCategoriesReturn, type UseCommentsArgs, type UseCommentsReturn, type UseEntityTitlesReturn, type UseUniversalEntitySearchArgs, type UseUniversalEntitySearchReturn, type WindowShellComponentProps, getContentRoleMeta, lazyPickerOverride, lazyWindowShell, useAssociationCandidates, useAssociationPickerBridge, useAssociationsStore, useAssociationsUiPorts, useCategories, useComments, useEntityTitles, useNotifier, useUniversalEntitySearch };
@@ -746,6 +746,7 @@ var ENTITY_TYPE_TOKENS = [
746
746
  "platform_repo",
747
747
  "platform_saved_view",
748
748
  "platform_schema",
749
+ "platform_secure_delivery",
749
750
  "platform_share_link",
750
751
  "podcast_race",
751
752
  "processed_document",
@@ -941,7 +942,6 @@ var ENTITY_TYPE_TOKENS = [
941
942
  "system_context_item",
942
943
  "system_error",
943
944
  "system_orgs",
944
- "system_personal_org_failure",
945
945
  "system_write_failure",
946
946
  "task",
947
947
  "task_user_state",
@@ -1628,7 +1628,9 @@ function useUniversalEntitySearch(args) {
1628
1628
  const store = useAssociationsStore();
1629
1629
  const [results, setResults] = useState3([]);
1630
1630
  const [loading, setLoading] = useState3(false);
1631
- const [isRecents, setIsRecents] = useState3(true);
1631
+ const [source, setSource] = useState3(
1632
+ emptyQueryMode === "candidates" ? "candidates" : "recents"
1633
+ );
1632
1634
  const runRef = useRef5(0);
1633
1635
  const tokensKey = (tokens ?? []).join(",");
1634
1636
  useEffect5(() => {
@@ -1639,25 +1641,36 @@ function useUniversalEntitySearch(args) {
1639
1641
  if (runRef.current !== run) return;
1640
1642
  setLoading(true);
1641
1643
  const activeTokens = tokensKey ? tokensKey.split(",") : store.registry.listableTokens();
1644
+ const browse = () => store.candidates.searchCandidatesAcrossTokens({
1645
+ tokens: activeTokens,
1646
+ search: trimmed,
1647
+ ownerId: ownerId ?? null,
1648
+ perTokenLimit
1649
+ });
1642
1650
  let next = [];
1643
- if (trimmed || emptyQueryMode === "candidates") {
1644
- next = await store.candidates.searchCandidatesAcrossTokens({
1645
- tokens: activeTokens,
1646
- search: trimmed,
1647
- ownerId: ownerId ?? null,
1648
- perTokenLimit
1649
- });
1651
+ let nextSource;
1652
+ if (trimmed) {
1653
+ next = await browse();
1654
+ nextSource = "search";
1655
+ } else if (emptyQueryMode === "candidates") {
1656
+ next = await browse();
1657
+ nextSource = "candidates";
1650
1658
  } else {
1651
1659
  next = await loadRecents(store, activeTokens);
1660
+ nextSource = "recents";
1661
+ if (next.length === 0 && runRef.current === run) {
1662
+ next = await browse();
1663
+ nextSource = "candidates";
1664
+ }
1652
1665
  }
1653
1666
  if (runRef.current !== run) return;
1654
1667
  setResults(next);
1655
- setIsRecents(!trimmed && emptyQueryMode === "recents");
1668
+ setSource(nextSource);
1656
1669
  setLoading(false);
1657
1670
  }, DEBOUNCE_MS);
1658
1671
  return () => clearTimeout(timer);
1659
1672
  }, [query, tokensKey, ownerId, enabled, perTokenLimit, emptyQueryMode, store]);
1660
- return { results, loading, isRecents };
1673
+ return { results, loading, isRecents: source === "recents", source };
1661
1674
  }
1662
1675
  async function loadRecents(store, tokens) {
1663
1676
  const res = await store.favorites.list();
@@ -2635,7 +2648,7 @@ function ListMessage({ children }) {
2635
2648
 
2636
2649
  // src/react/components/UniversalAssociationPicker.tsx
2637
2650
  import { useState as useState8 } from "react";
2638
- import { cn as cn4, Input as Input2 } from "@ai-matrx/design-system";
2651
+ import { Button, cn as cn4, Input as Input2 } from "@ai-matrx/design-system";
2639
2652
 
2640
2653
  // src/react/components/entityDoors.tsx
2641
2654
  import { cn as cn3 } from "@ai-matrx/design-system";
@@ -2726,7 +2739,15 @@ function attachedKey(token, id) {
2726
2739
  return `${token}:${id}`;
2727
2740
  }
2728
2741
  function UniversalAssociationPicker(props) {
2729
- const { attachedKeys, onAttach, onDetach, ownerId, orgId, className } = props;
2742
+ const {
2743
+ attachedKeys,
2744
+ onAttach,
2745
+ onDetach,
2746
+ ownerId,
2747
+ orgId,
2748
+ emptyQueryMode = "recents",
2749
+ className
2750
+ } = props;
2730
2751
  const store = useAssociationsStore();
2731
2752
  const { pickerOverrides } = useAssociationsUiPorts();
2732
2753
  const notifier = useNotifier();
@@ -2734,12 +2755,19 @@ function UniversalAssociationPicker(props) {
2734
2755
  const [query, setQuery] = useState8("");
2735
2756
  const [browseToken, setBrowseToken] = useState8(null);
2736
2757
  const [busyKey, setBusyKey] = useState8(null);
2737
- const { results, loading, isRecents } = useUniversalEntitySearch({
2758
+ const [overrideOpen, setOverrideOpen] = useState8(false);
2759
+ const [overrideMount, setOverrideMount] = useState8(0);
2760
+ const { results, loading, source } = useUniversalEntitySearch({
2738
2761
  query,
2739
2762
  tokens,
2740
2763
  ownerId: ownerId ?? null,
2741
- enabled: browseToken === null
2764
+ enabled: browseToken === null,
2765
+ emptyQueryMode
2742
2766
  });
2767
+ const selectToken = (next) => {
2768
+ setBrowseToken(next);
2769
+ setOverrideOpen(next !== null && Boolean(pickerOverrides?.[next]));
2770
+ };
2743
2771
  const toggle = async (c) => {
2744
2772
  const key = attachedKey(c.token, c.id);
2745
2773
  if (busyKey) return;
@@ -2772,7 +2800,7 @@ function UniversalAssociationPicker(props) {
2772
2800
  value: query,
2773
2801
  onChange: (e) => {
2774
2802
  setQuery(e.target.value);
2775
- if (browseToken) setBrowseToken(null);
2803
+ if (browseToken) selectToken(null);
2776
2804
  },
2777
2805
  placeholder: "Search everything\u2026",
2778
2806
  className: "pl-8 text-base",
@@ -2795,7 +2823,8 @@ function UniversalAssociationPicker(props) {
2795
2823
  "button",
2796
2824
  {
2797
2825
  type: "button",
2798
- onClick: () => setBrowseToken(active ? null : t),
2826
+ "aria-pressed": active,
2827
+ onClick: () => selectToken(active ? null : t),
2799
2828
  className: cn4(
2800
2829
  "inline-flex shrink-0 items-center gap-1 rounded-md border px-1.5 py-0.5 text-[11px] transition-colors",
2801
2830
  active ? "border-primary/50 bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground hover:bg-accent"
@@ -2813,20 +2842,62 @@ function UniversalAssociationPicker(props) {
2813
2842
  browseToken && BrowseOverride ? (
2814
2843
  // The token's canonical host picker (e.g. the stored-files browser)
2815
2844
  // owns per-token browsing when registered — never a plain list twin.
2816
- /* @__PURE__ */ jsx8(
2817
- BrowseOverride,
2845
+ // It opens in its own window; this body says where it went.
2846
+ /* @__PURE__ */ jsxs6(
2847
+ "div",
2818
2848
  {
2819
- open: true,
2820
- onOpenChange: (open) => {
2821
- if (!open) setBrowseToken(null);
2822
- },
2823
- token: browseToken,
2824
- orgId: orgId ?? null,
2825
- attachedIds: new Set(
2826
- [...attachedKeys].filter((k) => k.startsWith(`${browseToken}:`)).map((k) => k.slice(browseToken.length + 1))
2827
- ),
2828
- onAttach: (id, title) => onAttach(browseToken, id, title),
2829
- onDetach: (id) => onDetach(browseToken, id)
2849
+ role: "region",
2850
+ "aria-label": `${store.registry.getEntityInfo(browseToken).labelPlural} window`,
2851
+ className: "flex flex-1 flex-col items-center justify-center gap-3 px-4 py-8 text-center",
2852
+ children: [
2853
+ /* @__PURE__ */ jsx8("p", { className: "text-sm text-foreground", children: overrideOpen ? `The ${store.registry.getEntityInfo(browseToken).labelPlural.toLowerCase()} window is open.` : `The ${store.registry.getEntityInfo(browseToken).labelPlural.toLowerCase()} window is closed.` }),
2854
+ /* @__PURE__ */ jsx8("p", { className: "max-w-xs text-[12px] text-muted-foreground", children: overrideOpen ? "Check items there to attach them; uncheck to detach. Changes save as you go." : "Reopen it to pick more, or go back to search everything." }),
2855
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center justify-center gap-2", children: [
2856
+ /* @__PURE__ */ jsxs6(
2857
+ Button,
2858
+ {
2859
+ type: "button",
2860
+ size: "sm",
2861
+ variant: overrideOpen ? "outline" : "default",
2862
+ onClick: () => {
2863
+ setOverrideOpen(true);
2864
+ setOverrideMount((n) => n + 1);
2865
+ },
2866
+ children: [
2867
+ /* @__PURE__ */ jsx8(MaximizeIcon, { className: "mr-1.5 h-3.5 w-3.5" }),
2868
+ overrideOpen ? "Bring window to front" : "Reopen window"
2869
+ ]
2870
+ }
2871
+ ),
2872
+ /* @__PURE__ */ jsx8(
2873
+ Button,
2874
+ {
2875
+ type: "button",
2876
+ size: "sm",
2877
+ variant: "ghost",
2878
+ onClick: () => selectToken(null),
2879
+ children: "Back to search"
2880
+ }
2881
+ )
2882
+ ] }),
2883
+ overrideOpen && /* @__PURE__ */ jsx8(
2884
+ BrowseOverride,
2885
+ {
2886
+ open: true,
2887
+ onOpenChange: (open) => {
2888
+ if (!open) setOverrideOpen(false);
2889
+ },
2890
+ token: browseToken,
2891
+ orgId: orgId ?? null,
2892
+ attachedIds: new Set(
2893
+ [...attachedKeys].filter((k) => k.startsWith(`${browseToken}:`)).map((k) => k.slice(browseToken.length + 1))
2894
+ ),
2895
+ onAttach: (id, title) => onAttach(browseToken, id, title),
2896
+ onDetach: (id) => onDetach(browseToken, id)
2897
+ },
2898
+ overrideMount
2899
+ )
2900
+ ]
2830
2901
  }
2831
2902
  )
2832
2903
  ) : browseToken ? /* @__PURE__ */ jsx8("div", { className: "flex min-h-0 flex-1 flex-col", children: /* @__PURE__ */ jsx8(
@@ -2835,7 +2906,7 @@ function UniversalAssociationPicker(props) {
2835
2906
  token: browseToken,
2836
2907
  enabled: true,
2837
2908
  orgId,
2838
- onClose: () => setBrowseToken(null),
2909
+ onClose: () => selectToken(null),
2839
2910
  attachedIds: new Set(
2840
2911
  [...attachedKeys].filter((k) => k.startsWith(`${browseToken}:`)).map((k) => k.slice(browseToken.length + 1))
2841
2912
  ),
@@ -2848,8 +2919,8 @@ function UniversalAssociationPicker(props) {
2848
2919
  role: "region",
2849
2920
  "aria-label": "Association search results",
2850
2921
  className: "-mx-1 min-h-24 flex-1 overflow-y-auto overscroll-contain px-1",
2851
- children: results.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "py-6 text-center text-[12px] text-muted-foreground", children: loading ? "Searching\u2026" : query.trim() ? "No matches \u2014 narrow with a type chip to browse." : "No recent items. Type to search, or pick a type to browse." }) : /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
2852
- isRecents && /* @__PURE__ */ jsx8("p", { className: "px-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60", children: "Recent" }),
2922
+ children: results.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "py-6 text-center text-[12px] text-muted-foreground", children: loading ? "Searching\u2026" : query.trim() ? "No matches \u2014 narrow with a type chip to browse." : "Nothing to attach yet. Type to search, or pick a type to browse." }) : /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
2923
+ source !== "search" && /* @__PURE__ */ jsx8("p", { className: "px-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60", children: source === "recents" ? "Recent" : "Browse" }),
2853
2924
  [...groups.entries()].map(([token, items]) => {
2854
2925
  const info = store.registry.getEntityInfo(token);
2855
2926
  const GroupIcon = info.Icon ?? DefaultEntityIcon;
@@ -3769,7 +3840,7 @@ function titleize(token) {
3769
3840
 
3770
3841
  // src/react/components/AssociationCaptureToolbar.tsx
3771
3842
  import { useRef as useRef8, useState as useState12 } from "react";
3772
- import { Button, cn as cn9, Input as Input3 } from "@ai-matrx/design-system";
3843
+ import { Button as Button2, cn as cn9, Input as Input3 } from "@ai-matrx/design-system";
3773
3844
  import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3774
3845
  function AssociationCaptureToolbar({
3775
3846
  attach,
@@ -4126,7 +4197,7 @@ function CaptureToolbarAction({
4126
4197
  spinning
4127
4198
  }) {
4128
4199
  return /* @__PURE__ */ jsxs11(
4129
- Button,
4200
+ Button2,
4130
4201
  {
4131
4202
  type: "button",
4132
4203
  size: "sm",
@@ -4756,7 +4827,7 @@ function CategorySelect({
4756
4827
  import { useState as useState16 } from "react";
4757
4828
  import {
4758
4829
  Badge,
4759
- Button as Button2,
4830
+ Button as Button3,
4760
4831
  cn as cn11,
4761
4832
  Command as Command2,
4762
4833
  CommandEmpty as CommandEmpty2,
@@ -4921,7 +4992,7 @@ function CategoryTagPicker({
4921
4992
  )),
4922
4993
  /* @__PURE__ */ jsxs14(Popover2, { open, onOpenChange: setOpen, children: [
4923
4994
  /* @__PURE__ */ jsx17(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs14(
4924
- Button2,
4995
+ Button3,
4925
4996
  {
4926
4997
  variant: "outline",
4927
4998
  size: "sm",
@@ -5029,7 +5100,7 @@ function CategoryTagPicker({
5029
5100
 
5030
5101
  // src/react/components/CommentThread.tsx
5031
5102
  import { useState as useState17 } from "react";
5032
- import { Button as Button3, ErrorBox, Skeleton as Skeleton2, cn as cn12 } from "@ai-matrx/design-system";
5103
+ import { Button as Button4, ErrorBox, Skeleton as Skeleton2, cn as cn12 } from "@ai-matrx/design-system";
5033
5104
  import { formatRelativeTime } from "@ai-matrx/kit/format";
5034
5105
  import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
5035
5106
  var AUTHOR_DOOR_TOKEN = "user";
@@ -5142,7 +5213,7 @@ function CommentComposer({
5142
5213
  }
5143
5214
  ),
5144
5215
  /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
5145
- /* @__PURE__ */ jsxs15(Button3, { type: "submit", size: "sm", disabled: !body.trim() || submitting, children: [
5216
+ /* @__PURE__ */ jsxs15(Button4, { type: "submit", size: "sm", disabled: !body.trim() || submitting, children: [
5146
5217
  submitting && /* @__PURE__ */ jsx18(SpinnerIcon, { className: "mr-1 h-3 w-3 animate-spin" }),
5147
5218
  submitLabel
5148
5219
  ] }),
@@ -5221,7 +5292,7 @@ function CommentItem({
5221
5292
  return res;
5222
5293
  },
5223
5294
  trailing: /* @__PURE__ */ jsx18(
5224
- Button3,
5295
+ Button4,
5225
5296
  {
5226
5297
  type: "button",
5227
5298
  size: "sm",
@@ -5235,7 +5306,7 @@ function CommentItem({
5235
5306
  !editing && /* @__PURE__ */ jsx18("div", { className: "flex items-center gap-1 pl-7", children: confirmingDelete ? /* @__PURE__ */ jsxs15(Fragment5, { children: [
5236
5307
  /* @__PURE__ */ jsx18("span", { className: "text-xs text-destructive", children: "Deletes this comment for everyone." }),
5237
5308
  /* @__PURE__ */ jsxs15(
5238
- Button3,
5309
+ Button4,
5239
5310
  {
5240
5311
  type: "button",
5241
5312
  size: "sm",
@@ -5249,7 +5320,7 @@ function CommentItem({
5249
5320
  }
5250
5321
  ),
5251
5322
  /* @__PURE__ */ jsx18(
5252
- Button3,
5323
+ Button4,
5253
5324
  {
5254
5325
  type: "button",
5255
5326
  size: "sm",
@@ -5307,7 +5378,7 @@ function CommentItem({
5307
5378
  return res;
5308
5379
  },
5309
5380
  trailing: /* @__PURE__ */ jsx18(
5310
- Button3,
5381
+ Button4,
5311
5382
  {
5312
5383
  type: "button",
5313
5384
  size: "sm",
@@ -5386,7 +5457,7 @@ function CommentThread({
5386
5457
  children: [
5387
5458
  /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1", children: thread.error }),
5388
5459
  /* @__PURE__ */ jsx18(
5389
- Button3,
5460
+ Button4,
5390
5461
  {
5391
5462
  type: "button",
5392
5463
  size: "sm",