@botiverse/raft-ui 0.31.0 → 0.32.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.32.1](https://github.com/botiverse/raft-design/compare/v0.32.0...v0.32.1) (2026-10-23)
2
+
3
+ ### Fixed
4
+
5
+ - **ChoiceList** (wip): a row's name or description line that is cut off has its whole text as its `title` while it is cut off, so a long description can still be read with a mouse. ([#783](https://github.com/botiverse/raft-design/pull/783))
6
+ - Docs: https://raft-design.botiverse.build/components/choice-list/
7
+
8
+ ## [0.32.0](https://github.com/botiverse/raft-design/compare/v0.31.0...v0.32.0) (2026-10-23)
9
+
10
+ ### Added
11
+
12
+ - **ChoiceList** (wip): `matchedValues`, for a product with its own search (a ranked people search shared with mentions). With it ChoiceList shows the values the caller's search found, in the caller's order, instead of matching `searchText` itself; the chosen rows still come first and "No match" still shows. A value given twice shows once. Pass matches for the current text, and keep the previous ones while a slower search works. ([#780](https://github.com/botiverse/raft-design/pull/780))
13
+ - Docs: https://raft-design.botiverse.build/components/choice-list/
14
+
1
15
  ## [0.31.0](https://github.com/botiverse/raft-design/compare/v0.30.0...v0.31.0) (2026-10-23)
2
16
 
3
17
  ### Design System
package/dist/wip.d.mts CHANGED
@@ -762,6 +762,13 @@ type ChoiceListCommonProps = {
762
762
  */
763
763
  searchValue?: string;
764
764
  onSearchValueChange?: (value: string) => void;
765
+ /**
766
+ * The values of the items that match the search text, in the order to show
767
+ * them, for a caller with its own search (a ranked people search shared
768
+ * with mentions). With it ChoiceList doesn't match `searchText` itself; it
769
+ * still keeps the chosen rows first and says when nothing matches.
770
+ */
771
+ matchedValues?: readonly string[];
765
772
  /** The clear button's accessible name. */
766
773
  clearSearchLabel: string;
767
774
  /** The line under the chosen rows when nothing else matches. */
package/dist/wip.mjs CHANGED
@@ -2379,6 +2379,16 @@ function isDrawn(line) {
2379
2379
  function descriptionLines(description) {
2380
2380
  return (Array.isArray(description) ? description : [description]).filter(isDrawn);
2381
2381
  }
2382
+ function CutLine({ id, slot, className, children }) {
2383
+ const ref = useOverflowTitle();
2384
+ return /* @__PURE__ */ jsx("span", {
2385
+ ref,
2386
+ id,
2387
+ "data-slot": slot,
2388
+ className,
2389
+ children
2390
+ });
2391
+ }
2382
2392
  const NOT_TEXT_INPUTS = /* @__PURE__ */ new Set([
2383
2393
  "button",
2384
2394
  "checkbox",
@@ -2400,15 +2410,18 @@ function searchTextOf(item) {
2400
2410
  if (item.searchText !== void 0) return item.searchText;
2401
2411
  return typeof item.label === "string" ? item.label : "";
2402
2412
  }
2403
- function visibleItems(items, needle, pinned, chosen) {
2413
+ function visibleItems(items, needle, pinned, chosen, matchedValues) {
2404
2414
  if (!needle) return {
2405
2415
  rows: items,
2406
2416
  noMatch: false
2407
2417
  };
2408
- const matches = (item) => searchTextOf(item).toLowerCase().includes(needle);
2409
- const isPinned = (item) => pinned.includes(item.value);
2418
+ const matched = matchedValues ? new Set(matchedValues) : null;
2419
+ const matches = (item) => matched ? matched.has(item.value) : searchTextOf(item).toLowerCase().includes(needle);
2420
+ const pinnedSet = new Set(pinned);
2421
+ const isPinned = (item) => pinnedSet.has(item.value);
2410
2422
  const top = items.filter((item) => isPinned(item) || chosen.includes(item.value) && !matches(item));
2411
- const rest = items.filter((item) => !top.includes(item) && matches(item));
2423
+ const byValue = matchedValues ? new Map(items.map((item) => [item.value, item])) : null;
2424
+ const rest = (byValue && matched ? [...matched].flatMap((value) => byValue.get(value) ?? []) : items).filter((item) => !top.includes(item) && matches(item));
2412
2425
  return {
2413
2426
  rows: [...top, ...rest],
2414
2427
  noMatch: !items.some(matches)
@@ -2441,7 +2454,7 @@ function layoutSections(rows, groups) {
2441
2454
  };
2442
2455
  }
2443
2456
  function ChoiceList(props) {
2444
- const { items, search = "auto", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, disabled = false, searchLabel, searchPlaceholder, defaultSearchValue = "", searchValue, onSearchValueChange, clearSearchLabel, noMatchLabel, empty, groups, footer, fill = false, className } = props;
2457
+ const { items, search = "auto", "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, disabled = false, searchLabel, searchPlaceholder, defaultSearchValue = "", searchValue, onSearchValueChange, matchedValues, clearSearchLabel, noMatchLabel, empty, groups, footer, fill = false, className } = props;
2445
2458
  const value = props.value;
2446
2459
  const chosen = useMemo(() => value === null ? [] : typeof value === "string" ? [value] : value, [value]);
2447
2460
  const [ownQuery, setOwnQuery] = useState(defaultSearchValue);
@@ -2471,7 +2484,7 @@ function ChoiceList(props) {
2471
2484
  setPinnedFor(query);
2472
2485
  setPinned(chosen);
2473
2486
  }
2474
- const { rows, noMatch } = visibleItems(items, searchable ? query.trim().toLowerCase() : "", pinned, chosen);
2487
+ const { rows, noMatch } = visibleItems(items, searchable ? query.trim().toLowerCase() : "", pinned, chosen, matchedValues);
2475
2488
  const hasAction = rows.some((item) => item.action !== void 0 && item.action !== null);
2476
2489
  const slots = choiceList({
2477
2490
  scroll: searchable && !fill,
@@ -2536,16 +2549,16 @@ function ChoiceList(props) {
2536
2549
  /* @__PURE__ */ jsxs("span", {
2537
2550
  "data-slot": "choice-list-body",
2538
2551
  className: slots.body(),
2539
- children: [/* @__PURE__ */ jsx("span", {
2552
+ children: [/* @__PURE__ */ jsx(CutLine, {
2540
2553
  id: `${id}-label`,
2541
- "data-slot": "choice-list-label",
2554
+ slot: "choice-list-label",
2542
2555
  className: slots.label(),
2543
2556
  children: item.label
2544
2557
  }), lines.length > 0 ? /* @__PURE__ */ jsx("span", {
2545
2558
  id: `${id}-description`,
2546
2559
  className: "contents",
2547
- children: lines.map((line, index) => /* @__PURE__ */ jsx("span", {
2548
- "data-slot": "choice-list-description",
2560
+ children: lines.map((line, index) => /* @__PURE__ */ jsx(CutLine, {
2561
+ slot: "choice-list-description",
2549
2562
  className: slots.description(),
2550
2563
  children: line
2551
2564
  }, index))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.31.0",
3
+ "version": "0.32.1",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",