@djangocfg/layouts 1.2.49 โ 1.2.50
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.50",
|
|
4
4
|
"description": "Layout system and components for Unrealon applications",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DjangoCFG",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"check": "tsc --noEmit"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
-
"@djangocfg/api": "^1.2.
|
|
67
|
-
"@djangocfg/og-image": "^1.2.
|
|
68
|
-
"@djangocfg/ui": "^1.2.
|
|
66
|
+
"@djangocfg/api": "^1.2.50",
|
|
67
|
+
"@djangocfg/og-image": "^1.2.50",
|
|
68
|
+
"@djangocfg/ui": "^1.2.50",
|
|
69
69
|
"@hookform/resolvers": "^5.2.0",
|
|
70
70
|
"consola": "^3.4.2",
|
|
71
71
|
"lucide-react": "^0.468.0",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"vidstack": "0.6.15"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
|
-
"@djangocfg/typescript-config": "^1.2.
|
|
89
|
+
"@djangocfg/typescript-config": "^1.2.50",
|
|
90
90
|
"@types/node": "^24.7.2",
|
|
91
91
|
"@types/react": "19.2.2",
|
|
92
92
|
"@types/react-dom": "19.2.1",
|
|
@@ -16,36 +16,36 @@ export interface PackageInfo {
|
|
|
16
16
|
/**
|
|
17
17
|
* Package versions registry
|
|
18
18
|
* Auto-synced from package.json files
|
|
19
|
-
* Last updated: 2025-11-
|
|
19
|
+
* Last updated: 2025-11-21T06:17:17.842Z
|
|
20
20
|
*/
|
|
21
21
|
const PACKAGE_VERSIONS: PackageInfo[] = [
|
|
22
22
|
{
|
|
23
23
|
"name": "@djangocfg/ui",
|
|
24
|
-
"version": "1.2.
|
|
24
|
+
"version": "1.2.50"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"name": "@djangocfg/api",
|
|
28
|
-
"version": "1.2.
|
|
28
|
+
"version": "1.2.50"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "@djangocfg/layouts",
|
|
32
|
-
"version": "1.2.
|
|
32
|
+
"version": "1.2.50"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"name": "@djangocfg/markdown",
|
|
36
|
-
"version": "1.2.
|
|
36
|
+
"version": "1.2.50"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"name": "@djangocfg/og-image",
|
|
40
|
-
"version": "1.2.
|
|
40
|
+
"version": "1.2.50"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"name": "@djangocfg/eslint-config",
|
|
44
|
-
"version": "1.2.
|
|
44
|
+
"version": "1.2.50"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "@djangocfg/typescript-config",
|
|
48
|
-
"version": "1.2.
|
|
48
|
+
"version": "1.2.50"
|
|
49
49
|
}
|
|
50
50
|
];
|
|
51
51
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Form Components Configuration
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import React from 'react';
|
|
5
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
6
6
|
import {
|
|
7
7
|
Button,
|
|
8
8
|
ButtonLink,
|
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
Slider,
|
|
23
23
|
Combobox,
|
|
24
24
|
MultiSelect,
|
|
25
|
-
|
|
25
|
+
MultiSelectPro,
|
|
26
|
+
MultiSelectProAsync,
|
|
26
27
|
InputOTP,
|
|
27
28
|
InputOTPGroup,
|
|
28
29
|
InputOTPSlot,
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
FormLabel,
|
|
36
37
|
FormMessage,
|
|
37
38
|
Field,
|
|
39
|
+
useDebounce,
|
|
38
40
|
} from '@djangocfg/ui';
|
|
39
41
|
import { JsonSchemaForm } from '@djangocfg/ui/tools';
|
|
40
42
|
import type { ComponentConfig } from './types';
|
|
@@ -393,73 +395,352 @@ export const FORM_COMPONENTS: ComponentConfig[] = [
|
|
|
393
395
|
),
|
|
394
396
|
},
|
|
395
397
|
{
|
|
396
|
-
name: '
|
|
398
|
+
name: 'MultiSelectPro',
|
|
397
399
|
category: 'forms',
|
|
398
|
-
description: '
|
|
399
|
-
importPath: "import {
|
|
400
|
-
example: `
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
400
|
+
description: 'Advanced multi-select with animations, custom styling, grouped options, and comprehensive accessibility. Supports variants, icons, gradients, responsive design, and imperative control via ref.',
|
|
401
|
+
importPath: "import { MultiSelectPro } from '@djangocfg/ui';",
|
|
402
|
+
example: `import { MultiSelectPro } from '@djangocfg/ui';
|
|
403
|
+
import type { MultiSelectProOption } from '@djangocfg/ui';
|
|
404
|
+
import { useState } from 'react';
|
|
405
|
+
|
|
406
|
+
// Basic usage
|
|
407
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
408
|
+
|
|
409
|
+
<MultiSelectPro
|
|
410
|
+
options={[
|
|
411
|
+
{ value: "react", label: "React" },
|
|
412
|
+
{ value: "vue", label: "Vue.js" },
|
|
413
|
+
{ value: "angular", label: "Angular" },
|
|
414
|
+
]}
|
|
415
|
+
onValueChange={setSelected}
|
|
416
|
+
defaultValue={selected}
|
|
417
|
+
placeholder="Select frameworks..."
|
|
418
|
+
/>
|
|
419
|
+
|
|
420
|
+
// With custom styling and icons
|
|
421
|
+
const styledOptions = [
|
|
422
|
+
{
|
|
423
|
+
value: "react",
|
|
424
|
+
label: "React",
|
|
425
|
+
style: {
|
|
426
|
+
badgeColor: "#61DAFB",
|
|
427
|
+
iconColor: "#282C34",
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
value: "vue",
|
|
432
|
+
label: "Vue.js",
|
|
433
|
+
style: {
|
|
434
|
+
gradient: "linear-gradient(135deg, #4FC08D 0%, #42B883 100%)",
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
];
|
|
438
|
+
|
|
439
|
+
<MultiSelectPro
|
|
440
|
+
options={styledOptions}
|
|
441
|
+
onValueChange={setSelected}
|
|
442
|
+
variant="secondary"
|
|
443
|
+
animationConfig={{
|
|
444
|
+
badgeAnimation: "bounce",
|
|
445
|
+
popoverAnimation: "scale",
|
|
446
|
+
duration: 0.3,
|
|
447
|
+
}}
|
|
448
|
+
maxCount={3}
|
|
449
|
+
closeOnSelect={false}
|
|
450
|
+
/>
|
|
451
|
+
|
|
452
|
+
// With grouped options
|
|
453
|
+
const groupedOptions = [
|
|
454
|
+
{
|
|
455
|
+
heading: "Frontend Frameworks",
|
|
456
|
+
options: [
|
|
457
|
+
{ value: "react", label: "React" },
|
|
458
|
+
{ value: "vue", label: "Vue.js" },
|
|
459
|
+
{ value: "angular", label: "Angular", disabled: true },
|
|
460
|
+
],
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
heading: "Backend Technologies",
|
|
464
|
+
options: [
|
|
465
|
+
{ value: "node", label: "Node.js" },
|
|
466
|
+
{ value: "python", label: "Python" },
|
|
467
|
+
],
|
|
468
|
+
},
|
|
469
|
+
];
|
|
470
|
+
|
|
471
|
+
<MultiSelectPro
|
|
472
|
+
options={groupedOptions}
|
|
473
|
+
onValueChange={setSelected}
|
|
474
|
+
placeholder="Select technologies..."
|
|
475
|
+
searchable={true}
|
|
476
|
+
responsive={true}
|
|
477
|
+
minWidth="200px"
|
|
478
|
+
maxWidth="500px"
|
|
479
|
+
/>
|
|
480
|
+
|
|
481
|
+
// With imperative control via ref
|
|
482
|
+
import { useRef } from 'react';
|
|
483
|
+
import type { MultiSelectProRef } from '@djangocfg/ui';
|
|
484
|
+
|
|
485
|
+
const ref = useRef<MultiSelectProRef>(null);
|
|
486
|
+
|
|
487
|
+
// Later in code:
|
|
488
|
+
ref.current?.clear();
|
|
489
|
+
ref.current?.reset();
|
|
490
|
+
ref.current?.setSelectedValues(['react', 'vue']);
|
|
491
|
+
const values = ref.current?.getSelectedValues();`,
|
|
427
492
|
preview: (
|
|
428
|
-
<div className="space-y-
|
|
429
|
-
<
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
{
|
|
439
|
-
{
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
493
|
+
<div className="space-y-6">
|
|
494
|
+
<div className="space-y-2">
|
|
495
|
+
<p className="text-sm font-medium">Basic with animations:</p>
|
|
496
|
+
<MultiSelectPro
|
|
497
|
+
options={[
|
|
498
|
+
{ value: "react", label: "React" },
|
|
499
|
+
{ value: "vue", label: "Vue" },
|
|
500
|
+
{ value: "angular", label: "Angular" },
|
|
501
|
+
{ value: "svelte", label: "Svelte" },
|
|
502
|
+
]}
|
|
503
|
+
defaultValue={[]}
|
|
504
|
+
onValueChange={() => {}}
|
|
505
|
+
placeholder="Select frameworks..."
|
|
506
|
+
animationConfig={{
|
|
507
|
+
badgeAnimation: "bounce",
|
|
508
|
+
popoverAnimation: "scale",
|
|
509
|
+
duration: 0.3,
|
|
510
|
+
}}
|
|
511
|
+
maxCount={2}
|
|
512
|
+
className="w-[350px]"
|
|
513
|
+
/>
|
|
514
|
+
</div>
|
|
515
|
+
|
|
516
|
+
<div className="space-y-2">
|
|
517
|
+
<p className="text-sm font-medium">With variants and styles:</p>
|
|
518
|
+
<div className="grid grid-cols-2 gap-2">
|
|
519
|
+
<MultiSelectPro
|
|
520
|
+
options={[
|
|
521
|
+
{ value: "1", label: "Option 1" },
|
|
522
|
+
{ value: "2", label: "Option 2" },
|
|
523
|
+
]}
|
|
524
|
+
defaultValue={["1"]}
|
|
525
|
+
onValueChange={() => {}}
|
|
526
|
+
variant="secondary"
|
|
527
|
+
placeholder="Secondary"
|
|
528
|
+
maxCount={1}
|
|
529
|
+
/>
|
|
530
|
+
<MultiSelectPro
|
|
531
|
+
options={[
|
|
532
|
+
{ value: "1", label: "Option 1" },
|
|
533
|
+
{ value: "2", label: "Option 2" },
|
|
534
|
+
]}
|
|
535
|
+
defaultValue={["2"]}
|
|
536
|
+
onValueChange={() => {}}
|
|
537
|
+
variant="destructive"
|
|
538
|
+
placeholder="Destructive"
|
|
539
|
+
maxCount={1}
|
|
540
|
+
/>
|
|
541
|
+
</div>
|
|
542
|
+
</div>
|
|
543
|
+
|
|
544
|
+
<div className="space-y-2">
|
|
545
|
+
<p className="text-sm font-medium">Grouped options:</p>
|
|
546
|
+
<MultiSelectPro
|
|
547
|
+
options={[
|
|
548
|
+
{
|
|
549
|
+
heading: "Frontend",
|
|
550
|
+
options: [
|
|
551
|
+
{ value: "react", label: "React" },
|
|
552
|
+
{ value: "vue", label: "Vue" },
|
|
553
|
+
],
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
heading: "Backend",
|
|
557
|
+
options: [
|
|
558
|
+
{ value: "node", label: "Node.js" },
|
|
559
|
+
{ value: "python", label: "Python" },
|
|
560
|
+
],
|
|
561
|
+
},
|
|
562
|
+
]}
|
|
563
|
+
defaultValue={[]}
|
|
564
|
+
onValueChange={() => {}}
|
|
565
|
+
placeholder="Select from groups..."
|
|
566
|
+
className="w-[350px]"
|
|
567
|
+
maxCount={2}
|
|
568
|
+
/>
|
|
569
|
+
</div>
|
|
449
570
|
|
|
450
571
|
<div className="p-4 border rounded-md bg-muted/50">
|
|
451
572
|
<p className="text-sm font-medium mb-2">Features:</p>
|
|
452
|
-
<ul className="
|
|
453
|
-
<li
|
|
454
|
-
<li
|
|
455
|
-
<li
|
|
456
|
-
<li
|
|
457
|
-
<li
|
|
573
|
+
<ul className="grid grid-cols-2 gap-x-4 gap-y-1 text-sm text-muted-foreground">
|
|
574
|
+
<li>โจ Multiple variants (default, secondary, destructive, inverted)</li>
|
|
575
|
+
<li>๐ Custom badge colors & gradients</li>
|
|
576
|
+
<li>๐ Grouped options with separators</li>
|
|
577
|
+
<li>๐ซ Disabled options support</li>
|
|
578
|
+
<li>๐จ Badge animations (bounce, pulse, wiggle, fade, slide)</li>
|
|
579
|
+
<li>๐ Built-in search & filter</li>
|
|
580
|
+
<li>๐ฑ Responsive design (mobile/tablet/desktop)</li>
|
|
581
|
+
<li>๐ Width constraints (min/max)</li>
|
|
582
|
+
<li>โฟ Full accessibility (ARIA, keyboard nav)</li>
|
|
583
|
+
<li>๐ง Imperative control via ref</li>
|
|
584
|
+
<li>๐ Duplicate handling</li>
|
|
585
|
+
<li>๐๏ธ Auto-close, single-line, auto-size modes</li>
|
|
458
586
|
</ul>
|
|
459
587
|
</div>
|
|
460
588
|
</div>
|
|
461
589
|
),
|
|
462
590
|
},
|
|
591
|
+
{
|
|
592
|
+
name: 'MultiSelectProAsync',
|
|
593
|
+
category: 'forms',
|
|
594
|
+
description: 'Async multi-select with external API search, debouncing, and loading states. Perfect for large datasets and server-side filtering.',
|
|
595
|
+
importPath: "import { MultiSelectProAsync, useDebounce } from '@djangocfg/ui';",
|
|
596
|
+
example: `import { MultiSelectProAsync, useDebounce } from '@djangocfg/ui';
|
|
597
|
+
import { useState, useEffect } from 'react';
|
|
598
|
+
|
|
599
|
+
// Mock API function (replace with your actual API)
|
|
600
|
+
const searchAPI = async (query: string) => {
|
|
601
|
+
const response = await fetch(\`/api/search?q=\${query}\`);
|
|
602
|
+
return response.json();
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
function AsyncExample() {
|
|
606
|
+
const [searchValue, setSearchValue] = useState('');
|
|
607
|
+
const [options, setOptions] = useState([]);
|
|
608
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
609
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
610
|
+
|
|
611
|
+
// Debounce search to reduce API calls
|
|
612
|
+
const debouncedSearch = useDebounce(searchValue, 300);
|
|
613
|
+
|
|
614
|
+
// Fetch options when debounced search changes
|
|
615
|
+
useEffect(() => {
|
|
616
|
+
if (!debouncedSearch) {
|
|
617
|
+
setOptions([]);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const fetchOptions = async () => {
|
|
622
|
+
setIsLoading(true);
|
|
623
|
+
try {
|
|
624
|
+
const results = await searchAPI(debouncedSearch);
|
|
625
|
+
setOptions(results);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
console.error('Search failed:', error);
|
|
628
|
+
} finally {
|
|
629
|
+
setIsLoading(false);
|
|
630
|
+
}
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
fetchOptions();
|
|
634
|
+
}, [debouncedSearch]);
|
|
635
|
+
|
|
636
|
+
return (
|
|
637
|
+
<MultiSelectProAsync
|
|
638
|
+
// Search control (managed by parent)
|
|
639
|
+
searchValue={searchValue}
|
|
640
|
+
onSearchChange={setSearchValue}
|
|
641
|
+
isLoading={isLoading}
|
|
642
|
+
|
|
643
|
+
// Options from API
|
|
644
|
+
options={options}
|
|
645
|
+
|
|
646
|
+
// Selection
|
|
647
|
+
onValueChange={setSelected}
|
|
648
|
+
defaultValue={selected}
|
|
649
|
+
|
|
650
|
+
// UI
|
|
651
|
+
placeholder="Search and select..."
|
|
652
|
+
searchPlaceholder="Type to search..."
|
|
653
|
+
emptyText="No results found"
|
|
654
|
+
loadingText="Searching..."
|
|
655
|
+
|
|
656
|
+
// Features
|
|
657
|
+
variant="default"
|
|
658
|
+
maxCount={3}
|
|
659
|
+
closeOnSelect={false}
|
|
660
|
+
/>
|
|
661
|
+
);
|
|
662
|
+
}`,
|
|
663
|
+
preview: (() => {
|
|
664
|
+
// Demo component with mock data
|
|
665
|
+
const DemoAsync = () => {
|
|
666
|
+
const [searchValue, setSearchValue] = useState('');
|
|
667
|
+
const [selected, setSelected] = useState<string[]>([]);
|
|
668
|
+
const debouncedSearch = useDebounce(searchValue, 300);
|
|
669
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
670
|
+
|
|
671
|
+
// Mock database of countries
|
|
672
|
+
const allCountries = useMemo(() => [
|
|
673
|
+
{ value: 'us', label: 'United States' },
|
|
674
|
+
{ value: 'uk', label: 'United Kingdom' },
|
|
675
|
+
{ value: 'ca', label: 'Canada' },
|
|
676
|
+
{ value: 'au', label: 'Australia' },
|
|
677
|
+
{ value: 'de', label: 'Germany' },
|
|
678
|
+
{ value: 'fr', label: 'France' },
|
|
679
|
+
{ value: 'it', label: 'Italy' },
|
|
680
|
+
{ value: 'es', label: 'Spain' },
|
|
681
|
+
{ value: 'jp', label: 'Japan' },
|
|
682
|
+
{ value: 'cn', label: 'China' },
|
|
683
|
+
{ value: 'in', label: 'India' },
|
|
684
|
+
{ value: 'br', label: 'Brazil' },
|
|
685
|
+
{ value: 'mx', label: 'Mexico' },
|
|
686
|
+
{ value: 'ru', label: 'Russia' },
|
|
687
|
+
{ value: 'za', label: 'South Africa' },
|
|
688
|
+
], []);
|
|
689
|
+
|
|
690
|
+
// Filtered options based on debounced search
|
|
691
|
+
const filteredOptions = useMemo(() => {
|
|
692
|
+
if (!debouncedSearch) return [];
|
|
693
|
+
return allCountries.filter(country =>
|
|
694
|
+
country.label.toLowerCase().includes(debouncedSearch.toLowerCase())
|
|
695
|
+
);
|
|
696
|
+
}, [debouncedSearch, allCountries]);
|
|
697
|
+
|
|
698
|
+
// Simulate API loading
|
|
699
|
+
useEffect(() => {
|
|
700
|
+
if (debouncedSearch) {
|
|
701
|
+
setIsLoading(true);
|
|
702
|
+
const timer = setTimeout(() => setIsLoading(false), 300);
|
|
703
|
+
return () => clearTimeout(timer);
|
|
704
|
+
}
|
|
705
|
+
}, [debouncedSearch]);
|
|
706
|
+
|
|
707
|
+
return (
|
|
708
|
+
<div className="space-y-4">
|
|
709
|
+
<MultiSelectProAsync
|
|
710
|
+
searchValue={searchValue}
|
|
711
|
+
onSearchChange={setSearchValue}
|
|
712
|
+
isLoading={isLoading}
|
|
713
|
+
options={filteredOptions}
|
|
714
|
+
onValueChange={setSelected}
|
|
715
|
+
defaultValue={selected}
|
|
716
|
+
placeholder="Search countries..."
|
|
717
|
+
searchPlaceholder="Type to search countries..."
|
|
718
|
+
emptyText="No countries found"
|
|
719
|
+
loadingText="Searching..."
|
|
720
|
+
maxCount={2}
|
|
721
|
+
className="w-[350px]"
|
|
722
|
+
/>
|
|
723
|
+
|
|
724
|
+
<div className="p-4 border rounded-md bg-muted/50">
|
|
725
|
+
<p className="text-sm font-medium mb-2">Features:</p>
|
|
726
|
+
<ul className="space-y-1 text-sm text-muted-foreground">
|
|
727
|
+
<li>๐ <strong>Async search</strong> - Controlled search value for API integration</li>
|
|
728
|
+
<li>โฑ๏ธ <strong>Debouncing</strong> - Use useDebounce hook to reduce API calls</li>
|
|
729
|
+
<li>๐ <strong>Loading states</strong> - Shows spinner during data fetching</li>
|
|
730
|
+
<li>๐งน <strong>Auto-clear</strong> - Clears search when popover closes</li>
|
|
731
|
+
<li>โจ <strong>All MultiSelectPro features</strong> - Animations, variants, groups, etc.</li>
|
|
732
|
+
</ul>
|
|
733
|
+
<div className="mt-3 p-2 bg-muted rounded text-xs">
|
|
734
|
+
<strong>Try it:</strong> Type "united" or "india" to see async filtering
|
|
735
|
+
</div>
|
|
736
|
+
</div>
|
|
737
|
+
</div>
|
|
738
|
+
);
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
return <DemoAsync />;
|
|
742
|
+
})(),
|
|
743
|
+
},
|
|
463
744
|
{
|
|
464
745
|
name: 'InputOTP',
|
|
465
746
|
category: 'forms',
|
|
@@ -105,7 +105,7 @@ useEffect(() => {
|
|
|
105
105
|
}
|
|
106
106
|
}, [debouncedSearch]);
|
|
107
107
|
|
|
108
|
-
// With
|
|
108
|
+
// With MultiSelectPro (has built-in search)
|
|
109
109
|
const [searchValue, setSearchValue] = useState('');
|
|
110
110
|
const debouncedSearchValue = useDebounce(searchValue, 500);
|
|
111
111
|
|
|
@@ -116,10 +116,11 @@ useEffect(() => {
|
|
|
116
116
|
}
|
|
117
117
|
}, [debouncedSearchValue]);
|
|
118
118
|
|
|
119
|
-
<
|
|
120
|
-
searchValue={searchValue}
|
|
121
|
-
onSearchChange={setSearchValue}
|
|
119
|
+
<MultiSelectPro
|
|
122
120
|
options={filteredOptions}
|
|
121
|
+
onValueChange={setSelected}
|
|
122
|
+
placeholder="Search and select..."
|
|
123
|
+
searchable={true}
|
|
123
124
|
// ... other props
|
|
124
125
|
/>`,
|
|
125
126
|
preview: (
|