@ai-matrx/associations 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/react/index.cjs +165 -104
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +165 -104
- package/dist/react/index.js.map +1 -1
- package/package.json +3 -3
package/dist/react/index.js
CHANGED
|
@@ -2132,6 +2132,15 @@ function EntityCandidateList({
|
|
|
2132
2132
|
enabled,
|
|
2133
2133
|
...search.trim() ? { search: search.trim() } : {}
|
|
2134
2134
|
});
|
|
2135
|
+
const { results: recentCandidates, loading: recentsLoading } = useUniversalEntitySearch({
|
|
2136
|
+
query: "",
|
|
2137
|
+
tokens: [token],
|
|
2138
|
+
enabled: enabled && !search.trim()
|
|
2139
|
+
});
|
|
2140
|
+
const visibleRecents = search.trim() ? [] : recentCandidates;
|
|
2141
|
+
const recentIds = new Set(visibleRecents.map((candidate) => candidate.id));
|
|
2142
|
+
const ordinaryCandidates = search.trim() ? candidates : candidates.filter((candidate) => !recentIds.has(candidate.id));
|
|
2143
|
+
const visibleCount = visibleRecents.length + ordinaryCandidates.length;
|
|
2135
2144
|
const canCreate = info.titleColumn !== null && info.listCandidates === null;
|
|
2136
2145
|
const toggle = async (id, title) => {
|
|
2137
2146
|
if (busyId) return;
|
|
@@ -2162,7 +2171,7 @@ function EntityCandidateList({
|
|
|
2162
2171
|
}
|
|
2163
2172
|
)
|
|
2164
2173
|
] }),
|
|
2165
|
-
/* @__PURE__ */ jsx6("div", { className: "flex-1 min-h-0 overflow-y-auto -mx-1 px-1", children: loading &&
|
|
2174
|
+
/* @__PURE__ */ jsx6("div", { className: "flex-1 min-h-0 overflow-y-auto -mx-1 px-1", children: (loading || recentsLoading) && visibleCount === 0 ? /* @__PURE__ */ jsxs4(ListMessage, { children: [
|
|
2166
2175
|
/* @__PURE__ */ jsx6(SpinnerIcon, { className: "h-4 w-4 animate-spin" }),
|
|
2167
2176
|
"Loading\u2026"
|
|
2168
2177
|
] }) : error ? /* @__PURE__ */ jsxs4("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[12px] text-destructive", children: [
|
|
@@ -2177,23 +2186,69 @@ function EntityCandidateList({
|
|
|
2177
2186
|
children: "Retry"
|
|
2178
2187
|
}
|
|
2179
2188
|
)
|
|
2180
|
-
] }) :
|
|
2181
|
-
|
|
2182
|
-
|
|
2189
|
+
] }) : visibleCount === 0 ? /* @__PURE__ */ jsx6(ListMessage, { children: canCreate ? `Nothing to attach yet \u2014 create a new ${info.label.toLowerCase()} below.` : "Nothing to attach." }) : /* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
2190
|
+
visibleRecents.length > 0 && /* @__PURE__ */ jsx6(
|
|
2191
|
+
CandidateSection,
|
|
2192
|
+
{
|
|
2193
|
+
label: "Recent",
|
|
2194
|
+
candidates: visibleRecents,
|
|
2195
|
+
attachedIds,
|
|
2196
|
+
busyId,
|
|
2197
|
+
icon: /* @__PURE__ */ jsx6(Icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
2198
|
+
onToggle: toggle
|
|
2199
|
+
}
|
|
2200
|
+
),
|
|
2201
|
+
ordinaryCandidates.length > 0 && /* @__PURE__ */ jsx6(
|
|
2202
|
+
CandidateSection,
|
|
2203
|
+
{
|
|
2204
|
+
label: visibleRecents.length > 0 ? `All ${info.labelPlural}` : null,
|
|
2205
|
+
candidates: ordinaryCandidates,
|
|
2206
|
+
attachedIds,
|
|
2207
|
+
busyId,
|
|
2208
|
+
icon: /* @__PURE__ */ jsx6(Icon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
2209
|
+
onToggle: toggle
|
|
2210
|
+
}
|
|
2211
|
+
)
|
|
2212
|
+
] }) }),
|
|
2213
|
+
canCreate && /* @__PURE__ */ jsx6(
|
|
2214
|
+
CreateAndAttachFooter,
|
|
2215
|
+
{
|
|
2216
|
+
token,
|
|
2217
|
+
orgId,
|
|
2218
|
+
seed: search.trim(),
|
|
2219
|
+
onAttach,
|
|
2220
|
+
onCreated: reload
|
|
2221
|
+
}
|
|
2222
|
+
)
|
|
2223
|
+
] });
|
|
2224
|
+
}
|
|
2225
|
+
function CandidateSection({
|
|
2226
|
+
label,
|
|
2227
|
+
candidates,
|
|
2228
|
+
attachedIds,
|
|
2229
|
+
busyId,
|
|
2230
|
+
icon,
|
|
2231
|
+
onToggle
|
|
2232
|
+
}) {
|
|
2233
|
+
return /* @__PURE__ */ jsxs4("section", { className: "space-y-0.5", children: [
|
|
2234
|
+
label && /* @__PURE__ */ jsx6("p", { className: "px-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60", children: label }),
|
|
2235
|
+
/* @__PURE__ */ jsx6("ul", { className: "space-y-0.5", children: candidates.map((candidate) => {
|
|
2236
|
+
const attached = attachedIds.has(candidate.id);
|
|
2237
|
+
const busy = busyId === candidate.id;
|
|
2183
2238
|
return /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs4(
|
|
2184
2239
|
"button",
|
|
2185
2240
|
{
|
|
2186
2241
|
type: "button",
|
|
2187
2242
|
disabled: busy,
|
|
2188
|
-
onClick: () =>
|
|
2243
|
+
onClick: () => void onToggle(candidate.id, candidate.title),
|
|
2189
2244
|
className: cn2(
|
|
2190
2245
|
"group flex min-h-11 w-full items-center gap-2 rounded-md px-2.5 py-2 text-left text-sm transition-colors md:min-h-0",
|
|
2191
2246
|
"hover:bg-accent disabled:opacity-50",
|
|
2192
2247
|
attached && "bg-accent/40"
|
|
2193
2248
|
),
|
|
2194
2249
|
children: [
|
|
2195
|
-
|
|
2196
|
-
/* @__PURE__ */ jsx6("span", { className: "flex-1 min-w-0 truncate text-foreground", children:
|
|
2250
|
+
icon,
|
|
2251
|
+
/* @__PURE__ */ jsx6("span", { className: "flex-1 min-w-0 truncate text-foreground", children: candidate.title }),
|
|
2197
2252
|
/* @__PURE__ */ jsx6(
|
|
2198
2253
|
"span",
|
|
2199
2254
|
{
|
|
@@ -2206,18 +2261,8 @@ function EntityCandidateList({
|
|
|
2206
2261
|
)
|
|
2207
2262
|
]
|
|
2208
2263
|
}
|
|
2209
|
-
) },
|
|
2210
|
-
}) })
|
|
2211
|
-
canCreate && /* @__PURE__ */ jsx6(
|
|
2212
|
-
CreateAndAttachFooter,
|
|
2213
|
-
{
|
|
2214
|
-
token,
|
|
2215
|
-
orgId,
|
|
2216
|
-
seed: search.trim(),
|
|
2217
|
-
onAttach,
|
|
2218
|
-
onCreated: reload
|
|
2219
|
-
}
|
|
2220
|
-
)
|
|
2264
|
+
) }, candidate.id);
|
|
2265
|
+
}) })
|
|
2221
2266
|
] });
|
|
2222
2267
|
}
|
|
2223
2268
|
function CreateAndAttachFooter({
|
|
@@ -2487,27 +2532,35 @@ function UniversalAssociationPicker(props) {
|
|
|
2487
2532
|
),
|
|
2488
2533
|
loading && browseToken === null && /* @__PURE__ */ jsx8(SpinnerIcon, { className: "absolute right-2.5 top-1/2 h-4 w-4 -translate-y-1/2 animate-spin text-muted-foreground" })
|
|
2489
2534
|
] }),
|
|
2490
|
-
/* @__PURE__ */ jsx8(
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
"
|
|
2496
|
-
{
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2535
|
+
/* @__PURE__ */ jsx8(
|
|
2536
|
+
"div",
|
|
2537
|
+
{
|
|
2538
|
+
role: "group",
|
|
2539
|
+
"aria-label": "Entity type filters",
|
|
2540
|
+
className: "flex shrink-0 flex-nowrap gap-1 overflow-x-auto pb-1",
|
|
2541
|
+
children: tokens.map((t) => {
|
|
2542
|
+
const info = store.registry.getEntityInfo(t);
|
|
2543
|
+
const ChipIcon = info.Icon ?? DefaultEntityIcon;
|
|
2544
|
+
const active = browseToken === t;
|
|
2545
|
+
return /* @__PURE__ */ jsxs6(
|
|
2546
|
+
"button",
|
|
2547
|
+
{
|
|
2548
|
+
type: "button",
|
|
2549
|
+
onClick: () => setBrowseToken(active ? null : t),
|
|
2550
|
+
className: cn4(
|
|
2551
|
+
"inline-flex shrink-0 items-center gap-1 rounded-md border px-1.5 py-0.5 text-[11px] transition-colors",
|
|
2552
|
+
active ? "border-primary/50 bg-primary/10 text-foreground" : "border-border text-muted-foreground hover:text-foreground hover:bg-accent"
|
|
2553
|
+
),
|
|
2554
|
+
children: [
|
|
2555
|
+
/* @__PURE__ */ jsx8(ChipIcon, { className: "h-3 w-3" }),
|
|
2556
|
+
info.labelPlural
|
|
2557
|
+
]
|
|
2558
|
+
},
|
|
2559
|
+
t
|
|
2560
|
+
);
|
|
2561
|
+
})
|
|
2562
|
+
}
|
|
2563
|
+
),
|
|
2511
2564
|
browseToken && BrowseOverride ? (
|
|
2512
2565
|
// The token's canonical host picker (e.g. the stored-files browser)
|
|
2513
2566
|
// owns per-token browsing when registered — never a plain list twin.
|
|
@@ -2540,71 +2593,79 @@ function UniversalAssociationPicker(props) {
|
|
|
2540
2593
|
onAttach: (id, title) => onAttach(browseToken, id, title),
|
|
2541
2594
|
onDetach: (id) => onDetach(browseToken, id)
|
|
2542
2595
|
}
|
|
2543
|
-
) }) : /* @__PURE__ */ jsx8(
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
{
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2596
|
+
) }) : /* @__PURE__ */ jsx8(
|
|
2597
|
+
"div",
|
|
2598
|
+
{
|
|
2599
|
+
role: "region",
|
|
2600
|
+
"aria-label": "Association search results",
|
|
2601
|
+
className: "-mx-1 min-h-24 flex-1 overflow-y-auto overscroll-contain px-1",
|
|
2602
|
+
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: [
|
|
2603
|
+
isRecents && /* @__PURE__ */ jsx8("p", { className: "px-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/60", children: "Recent" }),
|
|
2604
|
+
[...groups.entries()].map(([token, items]) => {
|
|
2605
|
+
const info = store.registry.getEntityInfo(token);
|
|
2606
|
+
const GroupIcon = info.Icon ?? DefaultEntityIcon;
|
|
2607
|
+
return /* @__PURE__ */ jsxs6("div", { className: "space-y-0.5", children: [
|
|
2608
|
+
/* @__PURE__ */ jsxs6("p", { className: "flex items-center gap-1 px-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70", children: [
|
|
2609
|
+
/* @__PURE__ */ jsx8(GroupIcon, { className: "h-3 w-3" }),
|
|
2610
|
+
info.labelPlural
|
|
2611
|
+
] }),
|
|
2612
|
+
/* @__PURE__ */ jsx8("ul", { className: "space-y-0.5", children: items.map((c) => {
|
|
2613
|
+
const key = attachedKey(c.token, c.id);
|
|
2614
|
+
const attached = attachedKeys.has(key);
|
|
2615
|
+
const busy = busyKey === key;
|
|
2616
|
+
return /* @__PURE__ */ jsxs6(
|
|
2617
|
+
"li",
|
|
2618
|
+
{
|
|
2619
|
+
className: cn4(
|
|
2620
|
+
"group/entity-ref group flex items-center gap-1 rounded-md pr-1.5 transition-colors",
|
|
2621
|
+
"hover:bg-accent",
|
|
2622
|
+
attached && "bg-accent/40"
|
|
2623
|
+
),
|
|
2624
|
+
children: [
|
|
2625
|
+
/* @__PURE__ */ jsxs6(
|
|
2626
|
+
"button",
|
|
2627
|
+
{
|
|
2628
|
+
type: "button",
|
|
2629
|
+
disabled: busy,
|
|
2630
|
+
onClick: () => toggle(c),
|
|
2631
|
+
title: attached ? `Detach "${c.title}"` : `Attach "${c.title}"`,
|
|
2632
|
+
className: cn4(
|
|
2633
|
+
"flex min-w-0 flex-1 items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm",
|
|
2634
|
+
"disabled:opacity-50"
|
|
2635
|
+
),
|
|
2636
|
+
children: [
|
|
2637
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 truncate text-foreground", children: c.title }),
|
|
2638
|
+
/* @__PURE__ */ jsx8(
|
|
2639
|
+
"span",
|
|
2640
|
+
{
|
|
2641
|
+
className: cn4(
|
|
2642
|
+
"flex h-5 w-5 shrink-0 items-center justify-center rounded-full",
|
|
2643
|
+
attached ? "bg-primary text-primary-foreground" : "border border-border text-muted-foreground group-hover:border-primary/60"
|
|
2644
|
+
),
|
|
2645
|
+
children: busy ? /* @__PURE__ */ jsx8(SpinnerIcon, { className: "h-3 w-3 animate-spin" }) : attached ? /* @__PURE__ */ jsx8(CheckIcon, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx8(PlusIcon, { className: "h-3 w-3" })
|
|
2646
|
+
}
|
|
2647
|
+
)
|
|
2648
|
+
]
|
|
2649
|
+
}
|
|
2576
2650
|
),
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
token: c.token,
|
|
2596
|
-
id: c.id,
|
|
2597
|
-
name: c.title
|
|
2598
|
-
}
|
|
2599
|
-
)
|
|
2600
|
-
]
|
|
2601
|
-
},
|
|
2602
|
-
key
|
|
2603
|
-
);
|
|
2604
|
-
}) })
|
|
2605
|
-
] }, token);
|
|
2606
|
-
})
|
|
2607
|
-
] }) })
|
|
2651
|
+
/* @__PURE__ */ jsx8(
|
|
2652
|
+
DoorControlsSlot,
|
|
2653
|
+
{
|
|
2654
|
+
token: c.token,
|
|
2655
|
+
id: c.id,
|
|
2656
|
+
name: c.title
|
|
2657
|
+
}
|
|
2658
|
+
)
|
|
2659
|
+
]
|
|
2660
|
+
},
|
|
2661
|
+
key
|
|
2662
|
+
);
|
|
2663
|
+
}) })
|
|
2664
|
+
] }, token);
|
|
2665
|
+
})
|
|
2666
|
+
] })
|
|
2667
|
+
}
|
|
2668
|
+
)
|
|
2608
2669
|
] });
|
|
2609
2670
|
}
|
|
2610
2671
|
|