@djangocfg/layouts 1.2.48 → 1.2.49

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.48",
3
+ "version": "1.2.49",
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.48",
67
- "@djangocfg/og-image": "^1.2.48",
68
- "@djangocfg/ui": "^1.2.48",
66
+ "@djangocfg/api": "^1.2.49",
67
+ "@djangocfg/og-image": "^1.2.49",
68
+ "@djangocfg/ui": "^1.2.49",
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.48",
89
+ "@djangocfg/typescript-config": "^1.2.49",
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-20T17:19:40.883Z
19
+ * Last updated: 2025-11-21T05:40:14.485Z
20
20
  */
21
21
  const PACKAGE_VERSIONS: PackageInfo[] = [
22
22
  {
23
23
  "name": "@djangocfg/ui",
24
- "version": "1.2.48"
24
+ "version": "1.2.49"
25
25
  },
26
26
  {
27
27
  "name": "@djangocfg/api",
28
- "version": "1.2.48"
28
+ "version": "1.2.49"
29
29
  },
30
30
  {
31
31
  "name": "@djangocfg/layouts",
32
- "version": "1.2.48"
32
+ "version": "1.2.49"
33
33
  },
34
34
  {
35
35
  "name": "@djangocfg/markdown",
36
- "version": "1.2.48"
36
+ "version": "1.2.49"
37
37
  },
38
38
  {
39
39
  "name": "@djangocfg/og-image",
40
- "version": "1.2.48"
40
+ "version": "1.2.49"
41
41
  },
42
42
  {
43
43
  "name": "@djangocfg/eslint-config",
44
- "version": "1.2.48"
44
+ "version": "1.2.49"
45
45
  },
46
46
  {
47
47
  "name": "@djangocfg/typescript-config",
48
- "version": "1.2.48"
48
+ "version": "1.2.49"
49
49
  }
50
50
  ];
51
51
 
@@ -22,6 +22,7 @@ import {
22
22
  Slider,
23
23
  Combobox,
24
24
  MultiSelect,
25
+ SearchableMultiSelect,
25
26
  InputOTP,
26
27
  InputOTPGroup,
27
28
  InputOTPSlot,
@@ -391,6 +392,74 @@ export const FORM_COMPONENTS: ComponentConfig[] = [
391
392
  />
392
393
  ),
393
394
  },
395
+ {
396
+ name: 'SearchableMultiSelect',
397
+ category: 'forms',
398
+ description: 'Multi-select with integrated search and debounced filtering. Wraps MultiSelect with search functionality.',
399
+ importPath: "import { SearchableMultiSelect } from '@djangocfg/ui';",
400
+ example: `const [searchValue, setSearchValue] = useState('');
401
+ const [selectedValues, setSelectedValues] = useState<string[]>([]);
402
+
403
+ // Filter options based on search
404
+ const filteredOptions = useMemo(() => {
405
+ if (!searchValue) return allOptions;
406
+ return allOptions.filter(opt =>
407
+ opt.label.toLowerCase().includes(searchValue.toLowerCase())
408
+ );
409
+ }, [searchValue, allOptions]);
410
+
411
+ <SearchableMultiSelect
412
+ // Search props
413
+ searchValue={searchValue}
414
+ onSearchChange={setSearchValue}
415
+ searchPlaceholder="Search countries..."
416
+ searchDebounceMs={300}
417
+
418
+ // MultiSelect props
419
+ options={filteredOptions}
420
+ value={selectedValues}
421
+ onChange={setSelectedValues}
422
+ placeholder="Select countries..."
423
+ isLoading={isLoading}
424
+ emptyText="No countries found."
425
+ maxDisplay={3}
426
+ />`,
427
+ preview: (
428
+ <div className="space-y-4">
429
+ <SearchableMultiSelect
430
+ searchValue=""
431
+ onSearchChange={() => {}}
432
+ searchPlaceholder="Search frameworks..."
433
+ options={[
434
+ { value: "react", label: "React" },
435
+ { value: "vue", label: "Vue" },
436
+ { value: "angular", label: "Angular" },
437
+ { value: "svelte", label: "Svelte" },
438
+ { value: "next", label: "Next.js" },
439
+ { value: "nuxt", label: "Nuxt" },
440
+ { value: "gatsby", label: "Gatsby" },
441
+ ]}
442
+ value={[]}
443
+ onChange={() => {}}
444
+ placeholder="Select frameworks..."
445
+ emptyText="No framework found."
446
+ maxDisplay={2}
447
+ className="w-[300px]"
448
+ />
449
+
450
+ <div className="p-4 border rounded-md bg-muted/50">
451
+ <p className="text-sm font-medium mb-2">Features:</p>
452
+ <ul className="space-y-1 text-sm text-muted-foreground">
453
+ <li>• Integrated search input above MultiSelect</li>
454
+ <li>• Debounced search (default 300ms)</li>
455
+ <li>• Loading state support</li>
456
+ <li>• All MultiSelect features included</li>
457
+ <li>• Combine with API calls for dynamic filtering</li>
458
+ </ul>
459
+ </div>
460
+ </div>
461
+ ),
462
+ },
394
463
  {
395
464
  name: 'InputOTP',
396
465
  category: 'forms',
@@ -92,20 +92,56 @@ const countdown = useCountdown(targetDate);
92
92
  {
93
93
  name: 'useDebounce',
94
94
  category: 'hooks',
95
- description: 'Debounce value changes',
95
+ description: 'Debounce value changes to reduce API calls and improve performance. Perfect for search inputs and form fields.',
96
96
  importPath: "import { useDebounce } from '@djangocfg/ui';",
97
- example: `const [search, setSearch] = useState('');
98
- const debouncedSearch = useDebounce(search, 500);
97
+ example: `// Basic search debouncing
98
+ const [search, setSearch] = useState('');
99
+ const debouncedSearch = useDebounce(search, 300); // Default 300ms
99
100
 
100
- // debouncedSearch updates 500ms after last change`,
101
+ useEffect(() => {
102
+ if (debouncedSearch) {
103
+ // API call only fires 300ms after user stops typing
104
+ fetchResults(debouncedSearch);
105
+ }
106
+ }, [debouncedSearch]);
107
+
108
+ // With SearchableMultiSelect
109
+ const [searchValue, setSearchValue] = useState('');
110
+ const debouncedSearchValue = useDebounce(searchValue, 500);
111
+
112
+ useEffect(() => {
113
+ // Fetch options from API with debounced search
114
+ if (debouncedSearchValue) {
115
+ fetchOptions(debouncedSearchValue);
116
+ }
117
+ }, [debouncedSearchValue]);
118
+
119
+ <SearchableMultiSelect
120
+ searchValue={searchValue}
121
+ onSearchChange={setSearchValue}
122
+ options={filteredOptions}
123
+ // ... other props
124
+ />`,
101
125
  preview: (
102
126
  <div className="p-4 border rounded-md">
103
127
  <code className="text-sm">
104
- useDebounce(value, delay)
128
+ const debouncedValue = useDebounce(value, delay);
105
129
  </code>
106
- <p className="mt-2 text-sm text-muted-foreground">
107
- Debounces value changes with specified delay
108
- </p>
130
+ <div className="mt-3 space-y-2 text-sm text-muted-foreground">
131
+ <p><strong>Parameters:</strong></p>
132
+ <ul className="list-disc list-inside space-y-1 ml-2">
133
+ <li><code>value</code>: Any value to debounce</li>
134
+ <li><code>delay</code>: Delay in milliseconds (default: 300ms)</li>
135
+ </ul>
136
+ <p className="mt-2"><strong>Returns:</strong> Debounced value</p>
137
+ <p className="mt-2"><strong>Use Cases:</strong></p>
138
+ <ul className="list-disc list-inside space-y-1 ml-2">
139
+ <li>Search inputs (reduce API calls)</li>
140
+ <li>Form validation</li>
141
+ <li>Auto-save functionality</li>
142
+ <li>Scroll/resize event handlers</li>
143
+ </ul>
144
+ </div>
109
145
  </div>
110
146
  ),
111
147
  },