@botiverse/raft-ui 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/wip.d.mts +7 -0
- package/dist/wip.mjs +9 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [0.32.0](https://github.com/botiverse/raft-design/compare/v0.31.0...v0.32.0) (2026-10-23)
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- **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))
|
|
6
|
+
- Docs: https://raft-design.botiverse.build/components/choice-list/
|
|
7
|
+
|
|
1
8
|
## [0.31.0](https://github.com/botiverse/raft-design/compare/v0.30.0...v0.31.0) (2026-10-23)
|
|
2
9
|
|
|
3
10
|
### 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
|
@@ -2400,15 +2400,18 @@ function searchTextOf(item) {
|
|
|
2400
2400
|
if (item.searchText !== void 0) return item.searchText;
|
|
2401
2401
|
return typeof item.label === "string" ? item.label : "";
|
|
2402
2402
|
}
|
|
2403
|
-
function visibleItems(items, needle, pinned, chosen) {
|
|
2403
|
+
function visibleItems(items, needle, pinned, chosen, matchedValues) {
|
|
2404
2404
|
if (!needle) return {
|
|
2405
2405
|
rows: items,
|
|
2406
2406
|
noMatch: false
|
|
2407
2407
|
};
|
|
2408
|
-
const
|
|
2409
|
-
const
|
|
2408
|
+
const matched = matchedValues ? new Set(matchedValues) : null;
|
|
2409
|
+
const matches = (item) => matched ? matched.has(item.value) : searchTextOf(item).toLowerCase().includes(needle);
|
|
2410
|
+
const pinnedSet = new Set(pinned);
|
|
2411
|
+
const isPinned = (item) => pinnedSet.has(item.value);
|
|
2410
2412
|
const top = items.filter((item) => isPinned(item) || chosen.includes(item.value) && !matches(item));
|
|
2411
|
-
const
|
|
2413
|
+
const byValue = matchedValues ? new Map(items.map((item) => [item.value, item])) : null;
|
|
2414
|
+
const rest = (byValue && matched ? [...matched].flatMap((value) => byValue.get(value) ?? []) : items).filter((item) => !top.includes(item) && matches(item));
|
|
2412
2415
|
return {
|
|
2413
2416
|
rows: [...top, ...rest],
|
|
2414
2417
|
noMatch: !items.some(matches)
|
|
@@ -2441,7 +2444,7 @@ function layoutSections(rows, groups) {
|
|
|
2441
2444
|
};
|
|
2442
2445
|
}
|
|
2443
2446
|
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;
|
|
2447
|
+
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
2448
|
const value = props.value;
|
|
2446
2449
|
const chosen = useMemo(() => value === null ? [] : typeof value === "string" ? [value] : value, [value]);
|
|
2447
2450
|
const [ownQuery, setOwnQuery] = useState(defaultSearchValue);
|
|
@@ -2471,7 +2474,7 @@ function ChoiceList(props) {
|
|
|
2471
2474
|
setPinnedFor(query);
|
|
2472
2475
|
setPinned(chosen);
|
|
2473
2476
|
}
|
|
2474
|
-
const { rows, noMatch } = visibleItems(items, searchable ? query.trim().toLowerCase() : "", pinned, chosen);
|
|
2477
|
+
const { rows, noMatch } = visibleItems(items, searchable ? query.trim().toLowerCase() : "", pinned, chosen, matchedValues);
|
|
2475
2478
|
const hasAction = rows.some((item) => item.action !== void 0 && item.action !== null);
|
|
2476
2479
|
const slots = choiceList({
|
|
2477
2480
|
scroll: searchable && !fill,
|