@caratlogic/design-system 0.1.22 → 0.1.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.
- package/dist/components/molecules/ApiComboBox/ApiComboBox.d.ts +2 -1
- package/dist/components/molecules/ApiComboBox/ApiComboBox.d.ts.map +1 -1
- package/dist/components/molecules/SearchableSelect/SearchableSelect.d.ts.map +1 -1
- package/dist/components/molecules/SearchableSelect/SearchableSelect.hooks.d.ts.map +1 -1
- package/dist/index.cjs.js +24 -6
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +24 -6
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -14890,9 +14890,15 @@ function useSearchableSelect({ selectedItem, onChange, getOptionKey, getOptionLa
|
|
|
14890
14890
|
// ===== ASYNC MODE =====
|
|
14891
14891
|
const fetchPageRef = useRef(fetchPage);
|
|
14892
14892
|
fetchPageRef.current = fetchPage;
|
|
14893
|
+
// Bumped by every fresh (non-append) fetch. A response from an older search,
|
|
14894
|
+
// or a "load more" started before the search changed, is discarded so it
|
|
14895
|
+
// can't overwrite or pad the current results.
|
|
14896
|
+
const requestSeq = useRef(0);
|
|
14893
14897
|
const runFetch = useCallback(async (p, searchTerm, append) => {
|
|
14894
14898
|
if (!fetchPageRef.current)
|
|
14895
14899
|
return;
|
|
14900
|
+
const seq = append ? requestSeq.current : ++requestSeq.current;
|
|
14901
|
+
const isStale = () => seq !== requestSeq.current;
|
|
14896
14902
|
if (append)
|
|
14897
14903
|
setLoadingMore(true);
|
|
14898
14904
|
else
|
|
@@ -14903,6 +14909,8 @@ function useSearchableSelect({ selectedItem, onChange, getOptionKey, getOptionLa
|
|
|
14903
14909
|
limit: pageSize,
|
|
14904
14910
|
search: searchTerm,
|
|
14905
14911
|
});
|
|
14912
|
+
if (isStale())
|
|
14913
|
+
return;
|
|
14906
14914
|
setHasMore(res.hasMore);
|
|
14907
14915
|
setPage(p);
|
|
14908
14916
|
setItems((prev) => {
|
|
@@ -14933,12 +14941,16 @@ function useSearchableSelect({ selectedItem, onChange, getOptionKey, getOptionLa
|
|
|
14933
14941
|
});
|
|
14934
14942
|
}
|
|
14935
14943
|
catch {
|
|
14944
|
+
if (isStale())
|
|
14945
|
+
return;
|
|
14936
14946
|
setItems(selectedItem ? [selectedItem] : []);
|
|
14937
14947
|
setHasMore(false);
|
|
14938
14948
|
}
|
|
14939
14949
|
finally {
|
|
14940
|
-
|
|
14941
|
-
|
|
14950
|
+
if (!isStale()) {
|
|
14951
|
+
setLoading(false);
|
|
14952
|
+
setLoadingMore(false);
|
|
14953
|
+
}
|
|
14942
14954
|
}
|
|
14943
14955
|
}, [pageSize, selectedItem, getOptionKey]);
|
|
14944
14956
|
// Debounced search effect (async mode).
|
|
@@ -15098,10 +15110,14 @@ function SearchableSelect({ selectedItem, onChange, getOptionKey, getOptionLabel
|
|
|
15098
15110
|
? String(getOptionLabel(selectedItem))
|
|
15099
15111
|
: undefined, children: getOptionLabel(selectedItem) }));
|
|
15100
15112
|
}, [renderTrigger, selectedItem, searchPlaceholder, getOptionLabel]);
|
|
15113
|
+
const [activeValue, setActiveValue] = useState('');
|
|
15101
15114
|
return (jsxs(Popover, { open: open, onOpenChange: handleOpenChange, modal: modal, children: [jsx(PopoverTrigger, { asChild: true, children: jsxs(Button$1, { type: "button", variant: "outline", role: "combobox", "aria-expanded": open, "aria-label": ariaLabel, disabled: disabled, className: cn('w-full justify-start min-w-40 px-3 py-1.5',
|
|
15102
15115
|
// This trigger is a form control, not an action, so it takes the
|
|
15103
15116
|
// input disabled treatment instead of the Button's opacity fade.
|
|
15104
|
-
'disabled:bg-muted/50 disabled:text-label disabled:opacity-100', className), children: [jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [!selectedItem && !hideTriggerSearchIcon && (jsx(Search, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-muted-foreground" })), triggerNode] }), jsx(ChevronDown, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-muted-foreground opacity-60" })] }) }), jsx(PopoverContent, { style: { width: 'var(--radix-popover-trigger-width)' }, className: cn('p-0', popoverClassName), align: align, children: jsxs(Command, { shouldFilter: false, children: [jsx(CommandInput, { placeholder: searchPlaceholder, value: search, onValueChange: setSearch }), headerSlot, jsx(CommandList, { ref: listRef, onScroll: handleScroll,
|
|
15117
|
+
'disabled:bg-muted/50 disabled:text-label disabled:opacity-100', className), children: [jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [!selectedItem && !hideTriggerSearchIcon && (jsx(Search, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-muted-foreground" })), triggerNode] }), jsx(ChevronDown, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-muted-foreground opacity-60" })] }) }), jsx(PopoverContent, { style: { width: 'var(--radix-popover-trigger-width)' }, className: cn('p-0', popoverClassName), align: align, children: jsxs(Command, { shouldFilter: false, value: activeValue, onValueChange: setActiveValue, children: [jsx(CommandInput, { placeholder: searchPlaceholder, value: search, onValueChange: setSearch }), headerSlot, jsx(CommandList, { ref: listRef, onScroll: handleScroll,
|
|
15118
|
+
// cmdk keeps the last hovered row active for keyboard navigation;
|
|
15119
|
+
// clear it so the highlight doesn't linger once the pointer leaves.
|
|
15120
|
+
onMouseLeave: () => setActiveValue(''), className: LIST_MAX_HEIGHT_CLASS, children: loading ? (jsxs("div", { className: "flex items-center justify-center gap-2 p-3 text-sm text-muted-foreground", children: [jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }), "Loading\u2026"] })) : visibleItems.length === 0 ? (jsx(CommandEmpty, { children: emptyMessage })) : (jsxs(CommandGroup, { className: "p-1", children: [visibleItems.map((item) => {
|
|
15105
15121
|
const key = getOptionKey(item);
|
|
15106
15122
|
const isSelected = selectedKey === key;
|
|
15107
15123
|
if (renderOption) {
|
|
@@ -15202,10 +15218,12 @@ function ApiComboBox({ contactType, selectedItem, onSelect, fetchBusinessContact
|
|
|
15202
15218
|
const selected = selectedItem?.value ? selectedItem : null;
|
|
15203
15219
|
return (jsx(SearchableSelect, { selectedItem: selected, onChange: onSelect, getOptionKey: (i) => i.value, getOptionLabel: (i) => {
|
|
15204
15220
|
const c = i.contactData;
|
|
15221
|
+
// A pre-selected item carries only { value, label }; its label is already formatted.
|
|
15222
|
+
if (!c)
|
|
15223
|
+
return i.label;
|
|
15205
15224
|
const cid = i.contactId || i.code || '';
|
|
15206
|
-
const
|
|
15207
|
-
|
|
15208
|
-
return (`${company}${company ? ' ' : ''}${cid ? `(${cid})` : ''}${contactName ? ` · ${contactName}` : ''}`.trim() || i.label);
|
|
15225
|
+
const companyPart = [c.companyName, cid && `(${cid})`].filter(Boolean).join(' ');
|
|
15226
|
+
return [companyPart, c.contactName].filter(Boolean).join(' · ') || i.label;
|
|
15209
15227
|
}, getOptionSubLabel: (i) => {
|
|
15210
15228
|
const c = i.contactData;
|
|
15211
15229
|
const email = c?.email?.primary || '';
|