myoperator-mcp 0.2.290 → 0.2.291
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/index.js +88 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5465,6 +5465,29 @@ export interface SelectFieldProps {
|
|
|
5465
5465
|
id?: string;
|
|
5466
5466
|
/** Name attribute for form submission */
|
|
5467
5467
|
name?: string;
|
|
5468
|
+
/**
|
|
5469
|
+
* Fires when the user scrolls to the bottom of the open dropdown.
|
|
5470
|
+
* Use this to load the next page from the server. The callback is
|
|
5471
|
+
* forwarded to SelectContent's \`onViewportScrollEnd\` (debounced by
|
|
5472
|
+
* the native \`scrollend\` event), so it won't fire while a scroll is
|
|
5473
|
+
* still in progress.
|
|
5474
|
+
*
|
|
5475
|
+
* No virtualization is applied \u2014 all loaded items render to the DOM.
|
|
5476
|
+
* For >2k items consumers may notice some lag; virtualization is a
|
|
5477
|
+
* separate ticket if it becomes a real-world problem.
|
|
5478
|
+
*/
|
|
5479
|
+
onScrollEnd?: () => void;
|
|
5480
|
+
/**
|
|
5481
|
+
* When true, renders a small "Loading more\u2026" row at the bottom of
|
|
5482
|
+
* the options list. Set this to true while your API call is in flight
|
|
5483
|
+
* so the user knows more items are on the way.
|
|
5484
|
+
*/
|
|
5485
|
+
loadingMore?: boolean;
|
|
5486
|
+
/**
|
|
5487
|
+
* When false, prevents \`onScrollEnd\` from firing further and renders
|
|
5488
|
+
* an "End of list" footer row. Default true (keep firing).
|
|
5489
|
+
*/
|
|
5490
|
+
hasMore?: boolean;
|
|
5468
5491
|
}
|
|
5469
5492
|
|
|
5470
5493
|
/**
|
|
@@ -5483,6 +5506,34 @@ export interface SelectFieldProps {
|
|
|
5483
5506
|
* required
|
|
5484
5507
|
* />
|
|
5485
5508
|
* \`\`\`
|
|
5509
|
+
*
|
|
5510
|
+
* @example Lazy-load on scroll
|
|
5511
|
+
* \`\`\`tsx
|
|
5512
|
+
* const [items, setItems] = useState<SelectOption[]>([]);
|
|
5513
|
+
* const [loadingMore, setLoadingMore] = useState(false);
|
|
5514
|
+
* const [hasMore, setHasMore] = useState(true);
|
|
5515
|
+
* const page = useRef(0);
|
|
5516
|
+
*
|
|
5517
|
+
* const loadNext = async () => {
|
|
5518
|
+
* if (loadingMore || !hasMore) return;
|
|
5519
|
+
* setLoadingMore(true);
|
|
5520
|
+
* const { results, isLast } = await api.fetchTemplates(page.current);
|
|
5521
|
+
* setItems(prev => [...prev, ...results]);
|
|
5522
|
+
* setHasMore(!isLast);
|
|
5523
|
+
* page.current += 1;
|
|
5524
|
+
* setLoadingMore(false);
|
|
5525
|
+
* };
|
|
5526
|
+
*
|
|
5527
|
+
* useEffect(() => { loadNext(); }, []);
|
|
5528
|
+
*
|
|
5529
|
+
* <SelectField
|
|
5530
|
+
* label="Template"
|
|
5531
|
+
* options={items}
|
|
5532
|
+
* onScrollEnd={loadNext}
|
|
5533
|
+
* loadingMore={loadingMore}
|
|
5534
|
+
* hasMore={hasMore}
|
|
5535
|
+
* />
|
|
5536
|
+
* \`\`\`
|
|
5486
5537
|
*/
|
|
5487
5538
|
const SelectField = React.forwardRef(
|
|
5488
5539
|
(
|
|
@@ -5507,6 +5558,9 @@ const SelectField = React.forwardRef(
|
|
|
5507
5558
|
labelClassName,
|
|
5508
5559
|
id,
|
|
5509
5560
|
name,
|
|
5561
|
+
onScrollEnd,
|
|
5562
|
+
loadingMore,
|
|
5563
|
+
hasMore,
|
|
5510
5564
|
}: SelectFieldProps,
|
|
5511
5565
|
ref: React.Ref<HTMLButtonElement>
|
|
5512
5566
|
) => {
|
|
@@ -5586,6 +5640,15 @@ const SelectField = React.forwardRef(
|
|
|
5586
5640
|
|
|
5587
5641
|
const hasGroups = Object.keys(groupedOptions.groups).length > 0;
|
|
5588
5642
|
|
|
5643
|
+
// Count rendered options for the "End of list" footer (only show when at least one is visible).
|
|
5644
|
+
const totalRendered =
|
|
5645
|
+
groupedOptions.ungrouped.length +
|
|
5646
|
+
Object.values(groupedOptions.groups).reduce(
|
|
5647
|
+
(sum, items) => sum + items.length,
|
|
5648
|
+
0
|
|
5649
|
+
);
|
|
5650
|
+
const showEndOfList = hasMore === false && totalRendered > 0 && !loadingMore;
|
|
5651
|
+
|
|
5589
5652
|
// Handle search input change
|
|
5590
5653
|
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
5591
5654
|
setSearchQuery(e.target.value);
|
|
@@ -5638,7 +5701,9 @@ const SelectField = React.forwardRef(
|
|
|
5638
5701
|
<Loader2 className="absolute right-8 size-4 animate-spin text-semantic-text-muted" />
|
|
5639
5702
|
)}
|
|
5640
5703
|
</SelectTrigger>
|
|
5641
|
-
<SelectContent
|
|
5704
|
+
<SelectContent
|
|
5705
|
+
onViewportScrollEnd={hasMore !== false ? onScrollEnd : undefined}
|
|
5706
|
+
>
|
|
5642
5707
|
{/* Search input */}
|
|
5643
5708
|
{searchable && (
|
|
5644
5709
|
<div className="flex items-center gap-2 px-3 pb-1.5 border-b border-solid border-semantic-border-layout">
|
|
@@ -5697,6 +5762,28 @@ const SelectField = React.forwardRef(
|
|
|
5697
5762
|
No results found
|
|
5698
5763
|
</div>
|
|
5699
5764
|
)}
|
|
5765
|
+
|
|
5766
|
+
{/* Loading-more row (lazy-load) */}
|
|
5767
|
+
{loadingMore && (
|
|
5768
|
+
<div
|
|
5769
|
+
role="status"
|
|
5770
|
+
aria-live="polite"
|
|
5771
|
+
className="flex items-center justify-center gap-2 py-2 text-sm text-semantic-text-muted"
|
|
5772
|
+
>
|
|
5773
|
+
<Loader2 className="size-3.5 animate-spin" aria-hidden="true" />
|
|
5774
|
+
<span>Loading more\u2026</span>
|
|
5775
|
+
</div>
|
|
5776
|
+
)}
|
|
5777
|
+
|
|
5778
|
+
{/* End-of-list footer (lazy-load) */}
|
|
5779
|
+
{showEndOfList && (
|
|
5780
|
+
<div
|
|
5781
|
+
role="status"
|
|
5782
|
+
className="py-2 text-center text-xs text-semantic-text-muted"
|
|
5783
|
+
>
|
|
5784
|
+
End of list
|
|
5785
|
+
</div>
|
|
5786
|
+
)}
|
|
5700
5787
|
</SelectContent>
|
|
5701
5788
|
</Select>
|
|
5702
5789
|
|
package/package.json
CHANGED