@classytic/fluid 0.1.2 → 0.2.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/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use client";
2
- import { clsx } from 'clsx';
3
- import { twMerge } from 'tailwind-merge';
4
- import * as React5 from 'react';
5
- import { memo, useMemo, useCallback, forwardRef, createContext, useId, useContext, useState, useRef, useSyncExternalStore, useEffect, isValidElement } from 'react';
2
+ export { Container, Section } from './chunk-H3NFL3GJ.js';
3
+ export { ClientSubmitButton, ConfirmSheet, FormSheet, SheetWrapper, useIsMobile } from './chunk-J2YRTQE4.js';
4
+ import { cn } from './chunk-GUHK2DTW.js';
5
+ export { cn } from './chunk-GUHK2DTW.js';
6
+ import * as React3 from 'react';
7
+ import React3__default, { memo, useMemo, useState, useCallback, useSyncExternalStore, useRef, useEffect, isValidElement, Children, createElement, Fragment as Fragment$1 } from 'react';
6
8
  import { useRouter, useSearchParams } from 'next/navigation';
7
9
  import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '@/components/ui/accordion';
8
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -11,9 +13,9 @@ import { Pagination, PaginationContent, PaginationItem, PaginationPrevious, Pagi
11
13
  import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@/components/ui/card';
12
14
  import { Skeleton } from '@/components/ui/skeleton';
13
15
  import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from '@/components/ui/table';
14
- import { ChevronDown, Minus, Plus, X, Check, LoaderIcon, Wand2, ChevronUp, AlertTriangle, Loader2, AlertCircle, RefreshCw, Copy, Search, ArrowUp, ArrowDown, ArrowUpDown, MoreHorizontal, Sun, Moon, MinusIcon, ChevronUpIcon, ChevronDownIcon, ArrowLeft, ArrowRight, CalendarIcon, Filter, RotateCcw, ChevronLeft, ChevronRight, Tag } from 'lucide-react';
15
- import { Button } from '@/components/ui/button';
16
+ import { Check, ChevronLeft, ChevronRight, ChevronUp, ChevronDown, AlertTriangle, Loader2, AlertCircle, RefreshCw, InboxIcon, SearchX, FileX2, CheckCircle2, Info, X, Copy, Search, ArrowUp, ArrowDown, ArrowUpDown, MoreHorizontal, Sun, Moon, MinusIcon, ChevronUpIcon, ChevronDownIcon, ArrowLeft, ArrowRight, CalendarIcon, Wand2, Tag, Plus } from 'lucide-react';
16
17
  import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible';
18
+ import { Button } from '@/components/ui/button';
17
19
  import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@/components/ui/alert-dialog';
18
20
  import { Alert, AlertTitle, AlertDescription } from '@/components/ui/alert';
19
21
  import { useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
@@ -24,19 +26,18 @@ import { cva } from 'class-variance-authority';
24
26
  import { Item, ItemContent, ItemDescription } from '@/components/ui/item';
25
27
  import { useTheme } from 'next-themes';
26
28
  import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '@/components/ui/command';
27
- import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupButton, InputGroupTextarea } from '@/components/ui/input-group';
29
+ import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupTextarea, InputGroupButton } from '@/components/ui/input-group';
28
30
  import { Popover, PopoverTrigger, PopoverContent } from '@/components/ui/popover';
29
31
  import { Badge } from '@/components/ui/badge';
30
32
  import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
31
33
  import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable';
32
34
  import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
33
- import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter } from '@/components/ui/sheet';
34
35
  import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
35
36
  import { Controller } from 'react-hook-form';
36
37
  import { Input } from '@/components/ui/input';
37
38
  import { Field, FieldLabel, FieldDescription, FieldError, FieldContent } from '@/components/ui/field';
38
39
  import { Textarea } from '@/components/ui/textarea';
39
- import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel } from '@/components/ui/select';
40
+ import { Select, SelectTrigger, SelectValue, SelectContent, SelectGroup, SelectLabel, SelectItem } from '@/components/ui/select';
40
41
  import { Checkbox } from '@/components/ui/checkbox';
41
42
  import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
42
43
  import { Switch } from '@/components/ui/switch';
@@ -44,14 +45,94 @@ import { Calendar } from '@/components/ui/calendar';
44
45
  import { Combobox, ComboboxInput as ComboboxInput$1, ComboboxContent, ComboboxEmpty, ComboboxList, ComboboxItem } from '@/components/ui/combobox';
45
46
  import { startOfMonth, endOfMonth, eachDayOfInterval, getDay, isSameDay, subMonths, addMonths, format, isSameMonth, isValid } from 'date-fns';
46
47
 
47
- var __defProp = Object.defineProperty;
48
- var __export = (target, all) => {
49
- for (var name in all)
50
- __defProp(target, name, { get: all[name], enumerable: true });
48
+ // src/lib/storage.ts
49
+ var getStorageItem = (key, defaultValue = null) => {
50
+ if (typeof window === "undefined") return defaultValue;
51
+ try {
52
+ const item = window.localStorage.getItem(key);
53
+ if (!item) return defaultValue;
54
+ const parsed = JSON.parse(item);
55
+ if (parsed && typeof parsed === "object" && parsed.__expiresAt) {
56
+ const now = Date.now();
57
+ if (now > parsed.__expiresAt) {
58
+ window.localStorage.removeItem(key);
59
+ return defaultValue;
60
+ }
61
+ return parsed.value;
62
+ }
63
+ return parsed;
64
+ } catch (error) {
65
+ console.error(`Error reading localStorage key "${key}":`, error);
66
+ return defaultValue;
67
+ }
68
+ };
69
+ var setStorageItem = (key, value, ttl = null) => {
70
+ if (typeof window === "undefined") return false;
71
+ try {
72
+ let itemToStore = value;
73
+ if (ttl && typeof ttl === "number" && ttl > 0) {
74
+ itemToStore = {
75
+ value,
76
+ __expiresAt: Date.now() + ttl
77
+ };
78
+ }
79
+ window.localStorage.setItem(key, JSON.stringify(itemToStore));
80
+ return true;
81
+ } catch (error) {
82
+ console.error(`Error setting localStorage key "${key}":`, error);
83
+ return false;
84
+ }
85
+ };
86
+ var removeStorageItem = (key) => {
87
+ if (typeof window === "undefined") return false;
88
+ try {
89
+ window.localStorage.removeItem(key);
90
+ return true;
91
+ } catch (error) {
92
+ console.error(`Error removing localStorage key "${key}":`, error);
93
+ return false;
94
+ }
95
+ };
96
+ var clearStorage = () => {
97
+ if (typeof window === "undefined") return false;
98
+ try {
99
+ window.localStorage.clear();
100
+ return true;
101
+ } catch (error) {
102
+ console.error("Error clearing localStorage:", error);
103
+ return false;
104
+ }
105
+ };
106
+ var isStorageEmpty = (key) => {
107
+ const data = getStorageItem(key);
108
+ return !data || Array.isArray(data) && data.length === 0;
109
+ };
110
+ var generateUUID = () => {
111
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
112
+ return crypto.randomUUID();
113
+ }
114
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
115
+ const r = Math.random() * 16 | 0;
116
+ const v = c === "x" ? r : r & 3 | 8;
117
+ return v.toString(16);
118
+ });
119
+ };
120
+ var TTL = {
121
+ MINUTE: 60 * 1e3,
122
+ HOUR: 60 * 60 * 1e3,
123
+ DAY: 24 * 60 * 60 * 1e3,
124
+ WEEK: 7 * 24 * 60 * 60 * 1e3,
125
+ MONTH: 30 * 24 * 60 * 60 * 1e3
126
+ };
127
+ var storage = {
128
+ get: getStorageItem,
129
+ set: setStorageItem,
130
+ remove: removeStorageItem,
131
+ clear: clearStorage,
132
+ isEmpty: isStorageEmpty,
133
+ generateUUID,
134
+ TTL
51
135
  };
52
- function cn(...inputs) {
53
- return twMerge(clsx(inputs));
54
- }
55
136
 
56
137
  // src/lib/filter-utils.ts
57
138
  function buildFilterParams(filters, filterConfig) {
@@ -117,20 +198,6 @@ function getApiParams(searchParams) {
117
198
  }
118
199
  return params;
119
200
  }
120
- var MOBILE_BREAKPOINT = 768;
121
- function useIsMobile() {
122
- const [isMobile, setIsMobile] = React5.useState(void 0);
123
- React5.useEffect(() => {
124
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
125
- const onChange = () => {
126
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
127
- };
128
- mql.addEventListener("change", onChange);
129
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
130
- return () => mql.removeEventListener("change", onChange);
131
- }, []);
132
- return !!isMobile;
133
- }
134
201
  function useBaseSearch(config) {
135
202
  const {
136
203
  basePath,
@@ -171,9 +238,12 @@ function useBaseSearch(config) {
171
238
  });
172
239
  return initialFilters;
173
240
  });
241
+ const stableConfig = {
242
+ searchFields,
243
+ filterFields};
174
244
  const handleSearch = useCallback(() => {
175
245
  const params = new URLSearchParams(searchParams);
176
- clearSearchAndFilterParams(params, config);
246
+ clearSearchAndFilterParams(params, stableConfig);
177
247
  const searchParamsNew = buildSearchParams(searchType, searchValue, searchFields);
178
248
  for (const [key, value] of searchParamsNew) {
179
249
  params.set(key, value);
@@ -183,20 +253,10 @@ function useBaseSearch(config) {
183
253
  params.set(key, value);
184
254
  }
185
255
  router.push(`${basePath}?${params.toString()}`);
186
- }, [
187
- searchType,
188
- searchValue,
189
- filters,
190
- searchFields,
191
- filterFields,
192
- searchParams,
193
- router,
194
- basePath,
195
- config
196
- ]);
256
+ }, [searchType, searchValue, filters, searchFields, filterFields, searchParams, router, basePath, defaultSearchType]);
197
257
  const clearSearch = useCallback(() => {
198
258
  const params = new URLSearchParams(searchParams);
199
- clearSearchAndFilterParams(params, config);
259
+ clearSearchAndFilterParams(params, stableConfig);
200
260
  setSearchValue("");
201
261
  setSearchType(defaultSearchType);
202
262
  const resetFilters = {};
@@ -206,7 +266,7 @@ function useBaseSearch(config) {
206
266
  setFilters(resetFilters);
207
267
  const next = params.toString();
208
268
  router.push(next ? `${basePath}?${next}` : `${basePath}`);
209
- }, [searchParams, router, basePath, config, defaultSearchType, filterFields]);
269
+ }, [searchParams, router, basePath, defaultSearchType, searchFields, filterFields]);
210
270
  const getSearchParamsForApi = useCallback(() => {
211
271
  return getApiParams(searchParams);
212
272
  }, [searchParams]);
@@ -259,6 +319,12 @@ var useScrollDetection = (ref, delay = 100) => {
259
319
  canScrollRight: false,
260
320
  isScrollable: false
261
321
  });
322
+ const timeoutRef = useRef(void 0);
323
+ useEffect(() => {
324
+ return () => {
325
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
326
+ };
327
+ }, []);
262
328
  const checkScroll = useCallback(() => {
263
329
  const scrollContainer = ref.current?.querySelector(
264
330
  '[data-slot="scroll-area-viewport"]'
@@ -276,11 +342,105 @@ var useScrollDetection = (ref, delay = 100) => {
276
342
  });
277
343
  }, [ref]);
278
344
  const debouncedCheckScroll = useCallback(() => {
279
- const timeoutId = setTimeout(checkScroll, delay);
280
- return () => clearTimeout(timeoutId);
345
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
346
+ timeoutRef.current = setTimeout(checkScroll, delay);
281
347
  }, [checkScroll, delay]);
282
348
  return { ...scrollState, checkScroll: debouncedCheckScroll };
283
349
  };
350
+ function useDebounce(value, delay = 300) {
351
+ const [debounced, setDebounced] = useState(value);
352
+ useEffect(() => {
353
+ const timer = setTimeout(() => setDebounced(value), delay);
354
+ return () => clearTimeout(timer);
355
+ }, [value, delay]);
356
+ return debounced;
357
+ }
358
+ function useDebouncedCallback(callback, delay = 300) {
359
+ const timerRef = useRef(void 0);
360
+ const callbackRef = useRef(callback);
361
+ callbackRef.current = callback;
362
+ useEffect(() => {
363
+ return () => {
364
+ if (timerRef.current) clearTimeout(timerRef.current);
365
+ };
366
+ }, []);
367
+ return (...args) => {
368
+ if (timerRef.current) clearTimeout(timerRef.current);
369
+ timerRef.current = setTimeout(() => callbackRef.current(...args), delay);
370
+ };
371
+ }
372
+ function useCopyToClipboard(resetDelay = 2e3) {
373
+ const [copied, setCopied] = useState(false);
374
+ const [error, setError] = useState(null);
375
+ const timerRef = useRef(void 0);
376
+ useEffect(() => {
377
+ return () => {
378
+ if (timerRef.current) clearTimeout(timerRef.current);
379
+ };
380
+ }, []);
381
+ const reset = useCallback(() => {
382
+ setCopied(false);
383
+ setError(null);
384
+ }, []);
385
+ const copy = useCallback(
386
+ async (text) => {
387
+ if (!navigator?.clipboard) {
388
+ const err = new Error("Clipboard API not available");
389
+ setError(err);
390
+ return false;
391
+ }
392
+ try {
393
+ await navigator.clipboard.writeText(text);
394
+ setCopied(true);
395
+ setError(null);
396
+ if (timerRef.current) clearTimeout(timerRef.current);
397
+ timerRef.current = setTimeout(() => setCopied(false), resetDelay);
398
+ return true;
399
+ } catch (e) {
400
+ const err = e instanceof Error ? e : new Error("Copy failed");
401
+ setError(err);
402
+ setCopied(false);
403
+ return false;
404
+ }
405
+ },
406
+ [resetDelay]
407
+ );
408
+ return { copy, copied, error, reset };
409
+ }
410
+ function useLocalStorage(key, initialValue, ttl) {
411
+ const [storedValue, setStoredValue] = useState(() => {
412
+ const item = storage.get(key, initialValue);
413
+ return item !== null ? item : initialValue;
414
+ });
415
+ const keyRef = useRef(key);
416
+ const ttlRef = useRef(ttl);
417
+ useEffect(() => {
418
+ keyRef.current = key;
419
+ ttlRef.current = ttl;
420
+ }, [key, ttl]);
421
+ const setValue = useCallback((value) => {
422
+ setStoredValue((prev) => {
423
+ const nextValue = value instanceof Function ? value(prev) : value;
424
+ storage.set(keyRef.current, nextValue, ttlRef.current);
425
+ return nextValue;
426
+ });
427
+ }, []);
428
+ const removeValue = useCallback(() => {
429
+ storage.remove(keyRef.current);
430
+ setStoredValue(initialValue);
431
+ }, [initialValue]);
432
+ useEffect(() => {
433
+ const handleStorage = (e) => {
434
+ if (e.key === keyRef.current) {
435
+ const item = storage.get(keyRef.current, initialValue);
436
+ setStoredValue(item !== null ? item : initialValue);
437
+ }
438
+ };
439
+ window.addEventListener("storage", handleStorage);
440
+ return () => window.removeEventListener("storage", handleStorage);
441
+ }, [initialValue]);
442
+ return [storedValue, setValue, removeValue];
443
+ }
284
444
  var AccordionSection = memo(function AccordionSection2({
285
445
  title,
286
446
  icon,
@@ -309,13 +469,13 @@ var FaqAccordion = memo(function FaqAccordion2({
309
469
  items,
310
470
  defaultOpen,
311
471
  className,
312
- openMultiple = false
472
+ multiple = false
313
473
  }) {
314
474
  return /* @__PURE__ */ jsx(
315
475
  Accordion,
316
476
  {
317
477
  defaultValue: defaultOpen ? [defaultOpen] : [],
318
- openMultiple,
478
+ multiple,
319
479
  className: cn("w-full", className),
320
480
  children: items.map((item) => /* @__PURE__ */ jsxs(AccordionItem, { value: item.id, children: [
321
481
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "text-left", children: item.question }),
@@ -702,6 +862,29 @@ function ApiPagination({
702
862
  }
703
863
  );
704
864
  }
865
+ var CARD_VARIANTS = {
866
+ default: "",
867
+ outline: "border-2",
868
+ ghost: "border-0 shadow-none bg-transparent",
869
+ elevated: "shadow-lg border-0",
870
+ primary: "border-primary/20 bg-primary/5",
871
+ secondary: "border-secondary/20 bg-secondary/5",
872
+ destructive: "border-destructive/20 bg-destructive/5",
873
+ success: "border-green-500/20 bg-green-500/5",
874
+ warning: "border-yellow-500/20 bg-yellow-500/5"
875
+ };
876
+ var CARD_SIZES = {
877
+ sm: "p-3",
878
+ default: "p-6",
879
+ lg: "p-8",
880
+ xl: "p-10"
881
+ };
882
+ var CARD_CONTENT_SIZES = {
883
+ sm: "pt-3",
884
+ default: "pt-6",
885
+ lg: "pt-8",
886
+ xl: "pt-10"
887
+ };
705
888
  function CardWrapper({
706
889
  title,
707
890
  description,
@@ -716,48 +899,25 @@ function CardWrapper({
716
899
  hideHeader = false,
717
900
  ...props
718
901
  }) {
719
- const variants = {
720
- default: "",
721
- outline: "border-2",
722
- ghost: "border-0 shadow-none bg-transparent",
723
- elevated: "shadow-lg border-0",
724
- primary: "border-primary/20 bg-primary/5",
725
- secondary: "border-secondary/20 bg-secondary/5",
726
- destructive: "border-destructive/20 bg-destructive/5",
727
- success: "border-green-500/20 bg-green-500/5",
728
- warning: "border-yellow-500/20 bg-yellow-500/5"
729
- };
730
- const sizes2 = {
731
- sm: "p-3",
732
- default: "p-6",
733
- lg: "p-8",
734
- xl: "p-10"
735
- };
736
- const contentSizes = {
737
- sm: "pt-3",
738
- default: "pt-6",
739
- lg: "pt-8",
740
- xl: "pt-10"
741
- };
742
- return /* @__PURE__ */ jsxs(Card, { className: cn(variants[variant], className), ...props, children: [
743
- !hideHeader && (title || description) && /* @__PURE__ */ jsxs(CardHeader, { className: cn(sizes2[size], "pb-4", headerClassName), children: [
902
+ return /* @__PURE__ */ jsxs(Card, { className: cn(CARD_VARIANTS[variant], className), ...props, children: [
903
+ !hideHeader && (title || description) && /* @__PURE__ */ jsxs(CardHeader, { className: cn(CARD_SIZES[size], "pb-4", headerClassName), children: [
744
904
  title && /* @__PURE__ */ jsx(CardTitle, { className: "text-lg font-semibold", children: title }),
745
905
  description && /* @__PURE__ */ jsx(CardDescription, { children: description })
746
906
  ] }),
747
907
  /* @__PURE__ */ jsx(
748
908
  CardContent,
749
909
  {
750
- className: cn(hideHeader ? sizes2[size] : contentSizes[size], contentClassName),
910
+ className: cn(hideHeader ? CARD_SIZES[size] : CARD_CONTENT_SIZES[size], contentClassName),
751
911
  children
752
912
  }
753
913
  ),
754
- footer && /* @__PURE__ */ jsx(CardFooter, { className: cn(sizes2[size], "pt-4 border-t", footerClassName), children: /* @__PURE__ */ jsx("div", { className: "w-full", children: footer }) })
914
+ footer && /* @__PURE__ */ jsx(CardFooter, { className: cn(CARD_SIZES[size], "pt-4 border-t", footerClassName), children: /* @__PURE__ */ jsx("div", { className: "w-full", children: footer }) })
755
915
  ] });
756
916
  }
757
917
  function DataCard({ title, data, className, ...props }) {
758
918
  return /* @__PURE__ */ jsx(CardWrapper, { title, className: cn("space-y-4", className), ...props, children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-4", children: data.map((item, index) => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
759
919
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: item.label }),
760
- /* @__PURE__ */ jsx("p", { className: cn("text-lg font-semibold", item.color && `text-${item.color}-600`), children: item.value })
920
+ /* @__PURE__ */ jsx("p", { className: cn("text-lg font-semibold", item.color), children: item.value })
761
921
  ] }, index)) }) });
762
922
  }
763
923
  function LoadingCard({ title, description, className, ...props }) {
@@ -766,6 +926,27 @@ function LoadingCard({ title, description, className, ...props }) {
766
926
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Loading..." })
767
927
  ] }) });
768
928
  }
929
+ var STATS_CARD_VARIANTS = {
930
+ default: "",
931
+ success: "bg-green-50 border-green-200 dark:bg-green-950/30 dark:border-green-900",
932
+ warning: "bg-yellow-50 border-yellow-200 dark:bg-yellow-950/30 dark:border-yellow-900",
933
+ danger: "bg-red-50 border-red-200 dark:bg-red-950/30 dark:border-red-900",
934
+ info: "bg-blue-50 border-blue-200 dark:bg-blue-950/30 dark:border-blue-900"
935
+ };
936
+ var STATS_ICON_VARIANTS = {
937
+ default: "text-muted-foreground",
938
+ success: "text-green-600 dark:text-green-400",
939
+ warning: "text-yellow-600 dark:text-yellow-400",
940
+ danger: "text-red-600 dark:text-red-400",
941
+ info: "text-blue-600 dark:text-blue-400"
942
+ };
943
+ var STATS_ICON_WRAPPER_VARIANTS = {
944
+ default: "bg-muted border border-border",
945
+ success: "bg-green-100/50 dark:bg-green-900/30",
946
+ warning: "bg-yellow-100/50 dark:bg-yellow-900/30",
947
+ danger: "bg-red-100/50 dark:bg-red-900/30",
948
+ info: "bg-blue-100/50 dark:bg-blue-900/30"
949
+ };
769
950
  function StatsCard({
770
951
  title,
771
952
  value,
@@ -777,31 +958,10 @@ function StatsCard({
777
958
  iconClassName,
778
959
  ...props
779
960
  }) {
780
- const cardVariants = {
781
- default: "",
782
- success: "bg-green-50 border-green-200 dark:bg-green-950/30 dark:border-green-900",
783
- warning: "bg-yellow-50 border-yellow-200 dark:bg-yellow-950/30 dark:border-yellow-900",
784
- danger: "bg-red-50 border-red-200 dark:bg-red-950/30 dark:border-red-900",
785
- info: "bg-blue-50 border-blue-200 dark:bg-blue-950/30 dark:border-blue-900"
786
- };
787
- const iconVariants = {
788
- default: "text-muted-foreground",
789
- success: "text-green-600 dark:text-green-400",
790
- warning: "text-yellow-600 dark:text-yellow-400",
791
- danger: "text-red-600 dark:text-red-400",
792
- info: "text-blue-600 dark:text-blue-400"
793
- };
794
- const iconWrapperVariants = {
795
- default: "bg-muted border border-border",
796
- success: "bg-green-100/50 dark:bg-green-900/30",
797
- warning: "bg-yellow-100/50 dark:bg-yellow-900/30",
798
- danger: "bg-red-100/50 dark:bg-red-900/30",
799
- info: "bg-blue-100/50 dark:bg-blue-900/30"
800
- };
801
961
  return /* @__PURE__ */ jsxs(
802
962
  CardWrapper,
803
963
  {
804
- className: cn("relative overflow-hidden", cardVariants[statsVariant], className),
964
+ className: cn("relative overflow-hidden", STATS_CARD_VARIANTS[statsVariant], className),
805
965
  size: "sm",
806
966
  hideHeader: true,
807
967
  ...props,
@@ -814,8 +974,8 @@ function StatsCard({
814
974
  ] }),
815
975
  icon && /* @__PURE__ */ jsx("div", { className: cn(
816
976
  "p-2 rounded-md",
817
- iconWrapperVariants[statsVariant],
818
- iconVariants[statsVariant],
977
+ STATS_ICON_WRAPPER_VARIANTS[statsVariant],
978
+ STATS_ICON_VARIANTS[statsVariant],
819
979
  iconClassName
820
980
  ), children: icon })
821
981
  ] }),
@@ -966,39 +1126,6 @@ function SkeletonGrid({
966
1126
  };
967
1127
  return /* @__PURE__ */ jsx("div", { className: cn("grid gap-4", gridCols[columns], className), children: Array.from({ length: cards }).map((_, i) => /* @__PURE__ */ jsx(SkeletonCard, { ...cardProps }, i)) });
968
1128
  }
969
- function ClientSubmitButton({
970
- children,
971
- disabled,
972
- loading = false,
973
- loadingText,
974
- className,
975
- variant,
976
- size,
977
- form,
978
- ...props
979
- }) {
980
- const isDisabled = loading || disabled;
981
- const content = loading && loadingText ? loadingText : children;
982
- return /* @__PURE__ */ jsxs(
983
- Button,
984
- {
985
- type: "submit",
986
- form,
987
- "aria-disabled": isDisabled,
988
- "aria-busy": loading,
989
- className: cn("relative", className),
990
- disabled: isDisabled,
991
- variant,
992
- size,
993
- ...props,
994
- children: [
995
- content,
996
- loading && /* @__PURE__ */ jsx("span", { className: "animate-spin absolute right-4", children: /* @__PURE__ */ jsx(LoaderIcon, {}) }),
997
- /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", role: "status", children: loading ? "Loading" : "Submit form" })
998
- ]
999
- }
1000
- );
1001
- }
1002
1129
  function CollapsibleWrapper({
1003
1130
  children,
1004
1131
  trigger,
@@ -1084,10 +1211,11 @@ function CollapsibleCard({
1084
1211
  CollapsibleTrigger,
1085
1212
  {
1086
1213
  render: /* @__PURE__ */ jsx(
1087
- "div",
1214
+ "button",
1088
1215
  {
1216
+ type: "button",
1089
1217
  className: cn(
1090
- "flex items-center justify-between w-full px-4 py-3 cursor-pointer transition-colors hover:bg-secondary/5",
1218
+ "flex items-center justify-between w-full px-4 py-3 cursor-pointer transition-colors hover:bg-secondary/5 bg-transparent border-0 text-left",
1091
1219
  headerClassName
1092
1220
  )
1093
1221
  }
@@ -1127,7 +1255,10 @@ function CollapsibleSection({
1127
1255
  defaultOpen,
1128
1256
  triggerVariant: "ghost",
1129
1257
  triggerSize: "sm",
1130
- triggerClassName: cn("h-8 px-2 font-medium justify-between", labelClassName),
1258
+ triggerClassName: cn(
1259
+ "h-8 px-2 font-medium justify-between",
1260
+ labelClassName
1261
+ ),
1131
1262
  contentClassName: cn("pl-4 mt-1", contentClassName),
1132
1263
  className: cn("space-y-1", className),
1133
1264
  ...props,
@@ -1169,7 +1300,7 @@ function ConfirmDialog({
1169
1300
  }
1170
1301
  };
1171
1302
  const triggerChildren = trigger?.props?.children;
1172
- const triggerElement = trigger ? React5.cloneElement(trigger, { children: void 0 }) : null;
1303
+ const triggerElement = trigger ? React3.cloneElement(trigger, { children: void 0 }) : null;
1173
1304
  return /* @__PURE__ */ jsxs(AlertDialog, { open, onOpenChange, ...props, children: [
1174
1305
  triggerElement && /* @__PURE__ */ jsx(AlertDialogTrigger, { render: triggerElement, children: triggerChildren }),
1175
1306
  /* @__PURE__ */ jsxs(AlertDialogContent, { className: cn("max-w-md", className), children: [
@@ -1311,104 +1442,626 @@ function ErrorStateInline({
1311
1442
  }
1312
1443
  );
1313
1444
  }
1314
- async function copyToClipboard(text, options) {
1315
- try {
1316
- await navigator.clipboard.writeText(text);
1317
- return true;
1318
- } catch {
1319
- return false;
1445
+ var PRESETS = {
1446
+ noResults: {
1447
+ icon: SearchX,
1448
+ title: "No results found",
1449
+ description: "Try adjusting your search or filter criteria."
1450
+ },
1451
+ noData: {
1452
+ icon: InboxIcon,
1453
+ title: "No data yet",
1454
+ description: "Get started by creating your first item."
1455
+ },
1456
+ notFound: {
1457
+ icon: FileX2,
1458
+ title: "Not found",
1459
+ description: "The item you're looking for doesn't exist or has been removed."
1320
1460
  }
1321
- }
1322
- function CopyButton({
1323
- value,
1461
+ };
1462
+ function EmptyState({
1463
+ title = "Nothing here",
1464
+ description,
1465
+ icon: IconProp = InboxIcon,
1466
+ action,
1467
+ secondaryAction,
1468
+ variant = "default",
1324
1469
  className,
1325
- size = "sm",
1326
- variant = "ghost",
1327
- showToast = true,
1328
- toastMessage = "Copied to clipboard",
1329
- errorMessage = "Failed to copy to clipboard",
1330
- timeout = 2e3,
1331
- children,
1332
- ...props
1470
+ children
1333
1471
  }) {
1334
- const [copied, setCopied] = useState(false);
1335
- const handleCopy = async () => {
1336
- if (!value) return;
1337
- const success = await copyToClipboard(value);
1338
- if (success) {
1339
- setCopied(true);
1340
- setTimeout(() => setCopied(false), timeout);
1472
+ const isLucideIcon = typeof IconProp === "function";
1473
+ const Icon = IconProp;
1474
+ const iconElement = isLucideIcon ? /* @__PURE__ */ jsx(
1475
+ Icon,
1476
+ {
1477
+ className: cn(
1478
+ "text-muted-foreground/60",
1479
+ variant === "compact" ? "h-8 w-8" : "h-12 w-12"
1480
+ ),
1481
+ strokeWidth: 1.5
1341
1482
  }
1342
- };
1343
- return /* @__PURE__ */ jsx(
1344
- Button,
1483
+ ) : IconProp;
1484
+ if (variant === "compact") {
1485
+ return /* @__PURE__ */ jsxs(
1486
+ "div",
1487
+ {
1488
+ className: cn(
1489
+ "flex items-center gap-3 py-6 px-4 text-muted-foreground",
1490
+ className
1491
+ ),
1492
+ children: [
1493
+ iconElement,
1494
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1495
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: title }),
1496
+ description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground/80 mt-0.5", children: description })
1497
+ ] }),
1498
+ action
1499
+ ]
1500
+ }
1501
+ );
1502
+ }
1503
+ return /* @__PURE__ */ jsxs(
1504
+ "div",
1345
1505
  {
1346
- variant,
1347
- size,
1348
- className: cn("h-6 w-6 p-0", className),
1349
- onClick: handleCopy,
1350
- disabled: !value,
1351
- ...props,
1352
- children: children || (copied ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3" }))
1506
+ className: cn(
1507
+ "flex flex-col items-center justify-center text-center",
1508
+ variant === "card" && "rounded-lg border border-dashed border-muted-foreground/25 bg-muted/30",
1509
+ variant === "default" ? "py-16 px-6" : "py-12 px-8",
1510
+ className
1511
+ ),
1512
+ children: [
1513
+ /* @__PURE__ */ jsx(
1514
+ "div",
1515
+ {
1516
+ className: cn(
1517
+ "flex items-center justify-center rounded-full bg-muted/60",
1518
+ variant === "default" ? "h-20 w-20 mb-6" : "h-16 w-16 mb-5"
1519
+ ),
1520
+ children: iconElement
1521
+ }
1522
+ ),
1523
+ /* @__PURE__ */ jsx(
1524
+ "h3",
1525
+ {
1526
+ className: cn(
1527
+ "font-semibold tracking-tight",
1528
+ variant === "default" ? "text-lg" : "text-base"
1529
+ ),
1530
+ children: title
1531
+ }
1532
+ ),
1533
+ description && /* @__PURE__ */ jsx(
1534
+ "p",
1535
+ {
1536
+ className: cn(
1537
+ "text-muted-foreground max-w-sm mt-2",
1538
+ variant === "default" ? "text-sm" : "text-xs"
1539
+ ),
1540
+ children: description
1541
+ }
1542
+ ),
1543
+ children && /* @__PURE__ */ jsx("div", { className: "mt-4 w-full max-w-md", children }),
1544
+ (action || secondaryAction) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mt-6", children: [
1545
+ action,
1546
+ secondaryAction
1547
+ ] })
1548
+ ]
1353
1549
  }
1354
1550
  );
1355
1551
  }
1356
- function CopyText({
1357
- value,
1358
- displayValue,
1359
- className,
1360
- textClassName,
1361
- buttonClassName,
1362
- maxLength = 30,
1363
- showButton = true,
1364
- ...buttonProps
1365
- }) {
1366
- const truncatedValue = displayValue || (value && value.length > maxLength ? `${value.substring(0, maxLength)}...` : value || "N/A");
1367
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
1368
- /* @__PURE__ */ jsx("span", { className: cn("font-medium", textClassName), title: value || "N/A", children: truncatedValue }),
1369
- showButton && value && /* @__PURE__ */ jsx(CopyButton, { value, className: buttonClassName, ...buttonProps })
1370
- ] });
1552
+ function EmptyStateNoResults(props) {
1553
+ return /* @__PURE__ */ jsx(EmptyState, { ...PRESETS.noResults, ...props });
1371
1554
  }
1372
- function CopyCodeBlock({
1373
- value,
1374
- className,
1375
- language,
1376
- showLineNumbers = false,
1377
- ...buttonProps
1378
- }) {
1379
- return /* @__PURE__ */ jsxs("div", { className: cn("relative group", className), children: [
1380
- /* @__PURE__ */ jsx("pre", { className: "bg-muted p-4 rounded-md overflow-x-auto text-sm", children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : "", children: value }) }),
1381
- /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx(CopyButton, { value, variant: "secondary", size: "sm", ...buttonProps }) })
1382
- ] });
1555
+ function EmptyStateNoData(props) {
1556
+ return /* @__PURE__ */ jsx(EmptyState, { ...PRESETS.noData, ...props });
1383
1557
  }
1384
- var ScrollButton = ({ direction, onClick, visible, className }) => {
1385
- if (!visible) return null;
1386
- const handleClick = (e) => {
1387
- e.preventDefault();
1388
- e.stopPropagation();
1389
- onClick();
1390
- };
1391
- return /* @__PURE__ */ jsx(
1392
- "button",
1558
+ function EmptyStateNotFound(props) {
1559
+ return /* @__PURE__ */ jsx(EmptyState, { ...PRESETS.notFound, ...props });
1560
+ }
1561
+ var SIZES = {
1562
+ sm: "h-4 w-4",
1563
+ md: "h-6 w-6",
1564
+ lg: "h-10 w-10"
1565
+ };
1566
+ var TEXT_SIZES = {
1567
+ sm: "text-xs",
1568
+ md: "text-sm",
1569
+ lg: "text-base"
1570
+ };
1571
+ function LoadingState({
1572
+ text,
1573
+ variant = "default",
1574
+ size = "md",
1575
+ className
1576
+ }) {
1577
+ const spinner = /* @__PURE__ */ jsx(
1578
+ Loader2,
1579
+ {
1580
+ className: cn(SIZES[size], "animate-spin text-muted-foreground")
1581
+ }
1582
+ );
1583
+ if (variant === "minimal") {
1584
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center justify-center", className), children: spinner });
1585
+ }
1586
+ if (variant === "inline") {
1587
+ return /* @__PURE__ */ jsxs(
1588
+ "div",
1589
+ {
1590
+ className: cn(
1591
+ "flex items-center gap-2 text-muted-foreground",
1592
+ className
1593
+ ),
1594
+ children: [
1595
+ spinner,
1596
+ text && /* @__PURE__ */ jsx("span", { className: TEXT_SIZES[size], children: text })
1597
+ ]
1598
+ }
1599
+ );
1600
+ }
1601
+ return /* @__PURE__ */ jsxs(
1602
+ "div",
1393
1603
  {
1394
- type: "button",
1395
1604
  className: cn(
1396
- "absolute top-1/2 -translate-y-1/2 z-50",
1397
- "flex items-center justify-center",
1398
- "size-10 rounded-md shadow-lg border-2 border-border",
1399
- "bg-background hover:bg-muted",
1400
- "transition-transform duration-200",
1401
- "hover:scale-105 active:scale-95",
1402
- direction === "left" ? "left-2" : "right-2",
1605
+ "flex flex-col items-center justify-center gap-3 py-12 px-6",
1403
1606
  className
1404
1607
  ),
1405
- onClick: handleClick,
1406
- onMouseDown: (e) => e.stopPropagation(),
1407
- "aria-label": `Scroll ${direction}`,
1408
- children: direction === "left" ? /* @__PURE__ */ jsx(ChevronLeft, { className: "size-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-5" })
1608
+ children: [
1609
+ spinner,
1610
+ text && /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground", TEXT_SIZES[size]), children: text })
1611
+ ]
1409
1612
  }
1410
1613
  );
1614
+ }
1615
+ function LoadingOverlay({
1616
+ text,
1617
+ visible = true,
1618
+ className,
1619
+ children
1620
+ }) {
1621
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
1622
+ children,
1623
+ visible && /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 rounded-[inherit] bg-background/90 backdrop-blur-sm", children: [
1624
+ /* @__PURE__ */ jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }),
1625
+ text && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground font-medium", children: text })
1626
+ ] })
1627
+ ] });
1628
+ }
1629
+ var VARIANT_MAP = {
1630
+ info: {
1631
+ icon: Info,
1632
+ bg: "bg-blue-50 dark:bg-blue-950/30",
1633
+ border: "border-blue-200 dark:border-blue-800",
1634
+ text: "text-blue-800 dark:text-blue-200",
1635
+ iconColor: "text-blue-500 dark:text-blue-400"
1636
+ },
1637
+ warning: {
1638
+ icon: AlertTriangle,
1639
+ bg: "bg-amber-50 dark:bg-amber-950/30",
1640
+ border: "border-amber-200 dark:border-amber-800",
1641
+ text: "text-amber-800 dark:text-amber-200",
1642
+ iconColor: "text-amber-500 dark:text-amber-400"
1643
+ },
1644
+ success: {
1645
+ icon: CheckCircle2,
1646
+ bg: "bg-emerald-50 dark:bg-emerald-950/30",
1647
+ border: "border-emerald-200 dark:border-emerald-800",
1648
+ text: "text-emerald-800 dark:text-emerald-200",
1649
+ iconColor: "text-emerald-500 dark:text-emerald-400"
1650
+ },
1651
+ error: {
1652
+ icon: AlertCircle,
1653
+ bg: "bg-red-50 dark:bg-red-950/30",
1654
+ border: "border-red-200 dark:border-red-800",
1655
+ text: "text-red-800 dark:text-red-200",
1656
+ iconColor: "text-red-500 dark:text-red-400"
1657
+ }
1411
1658
  };
1659
+ function StatusBanner({
1660
+ variant = "info",
1661
+ children,
1662
+ icon: CustomIcon,
1663
+ dismissible = false,
1664
+ onDismiss,
1665
+ action,
1666
+ className
1667
+ }) {
1668
+ const [dismissed, setDismissed] = React3.useState(false);
1669
+ if (dismissed) return null;
1670
+ const config = VARIANT_MAP[variant];
1671
+ const Icon = CustomIcon || config.icon;
1672
+ const handleDismiss = () => {
1673
+ setDismissed(true);
1674
+ onDismiss?.();
1675
+ };
1676
+ return /* @__PURE__ */ jsxs(
1677
+ "div",
1678
+ {
1679
+ role: "alert",
1680
+ className: cn(
1681
+ "flex items-center gap-3 rounded-lg border px-4 py-3",
1682
+ config.bg,
1683
+ config.border,
1684
+ config.text,
1685
+ className
1686
+ ),
1687
+ children: [
1688
+ /* @__PURE__ */ jsx(
1689
+ Icon,
1690
+ {
1691
+ className: cn("h-4 w-4 shrink-0", config.iconColor),
1692
+ strokeWidth: 2
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0 text-sm", children }),
1696
+ action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action }),
1697
+ dismissible && /* @__PURE__ */ jsxs(
1698
+ Button,
1699
+ {
1700
+ variant: "ghost",
1701
+ size: "icon",
1702
+ className: cn(
1703
+ "h-6 w-6 shrink-0 hover:bg-transparent opacity-60 hover:opacity-100",
1704
+ config.text
1705
+ ),
1706
+ onClick: handleDismiss,
1707
+ children: [
1708
+ /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" }),
1709
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Dismiss" })
1710
+ ]
1711
+ }
1712
+ )
1713
+ ]
1714
+ }
1715
+ );
1716
+ }
1717
+ function normalizeStep(step) {
1718
+ return typeof step === "string" ? { label: step } : step;
1719
+ }
1720
+ var StepCircle = React3.memo(function StepCircle2({
1721
+ index,
1722
+ isCompleted,
1723
+ isActive,
1724
+ icon,
1725
+ variant
1726
+ }) {
1727
+ const size = variant === "compact" ? "h-7 w-7" : "h-8 w-8";
1728
+ const iconSize = variant === "compact" ? "h-3.5 w-3.5" : "h-4 w-4";
1729
+ return /* @__PURE__ */ jsx(
1730
+ "span",
1731
+ {
1732
+ className: cn(
1733
+ "relative flex items-center justify-center rounded-full text-xs font-semibold shrink-0 transition-all duration-200",
1734
+ size,
1735
+ isCompleted ? "bg-primary text-primary-foreground" : isActive ? "bg-primary text-primary-foreground ring-2 ring-primary/20 ring-offset-2 ring-offset-background" : "border-2 border-muted-foreground/25 bg-background text-muted-foreground"
1736
+ ),
1737
+ children: isCompleted ? /* @__PURE__ */ jsx(Check, { className: iconSize, strokeWidth: 3 }) : icon || index + 1
1738
+ }
1739
+ );
1740
+ });
1741
+ var StepConnector = React3.memo(function StepConnector2({
1742
+ isCompleted,
1743
+ isVertical
1744
+ }) {
1745
+ if (isVertical) {
1746
+ return /* @__PURE__ */ jsx("div", { className: "flex justify-center w-8 py-1", children: /* @__PURE__ */ jsx(
1747
+ "div",
1748
+ {
1749
+ className: cn(
1750
+ "w-px h-6 transition-colors duration-200",
1751
+ isCompleted ? "bg-primary" : "bg-border"
1752
+ )
1753
+ }
1754
+ ) });
1755
+ }
1756
+ return /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center min-w-4 mt-4", children: /* @__PURE__ */ jsx(
1757
+ "div",
1758
+ {
1759
+ className: cn(
1760
+ "h-px w-full transition-colors duration-200",
1761
+ isCompleted ? "bg-primary" : "bg-border"
1762
+ )
1763
+ }
1764
+ ) });
1765
+ });
1766
+ function HorizontalStepper({
1767
+ steps,
1768
+ currentStep,
1769
+ variant,
1770
+ onStepClick
1771
+ }) {
1772
+ const activeRef = React3.useRef(null);
1773
+ const navRef = React3.useRef(null);
1774
+ React3.useEffect(() => {
1775
+ if (activeRef.current && navRef.current) {
1776
+ activeRef.current.scrollIntoView({
1777
+ behavior: "smooth",
1778
+ block: "nearest",
1779
+ inline: "center"
1780
+ });
1781
+ }
1782
+ }, [currentStep]);
1783
+ return /* @__PURE__ */ jsx(
1784
+ "nav",
1785
+ {
1786
+ ref: navRef,
1787
+ "aria-label": "Progress",
1788
+ role: "list",
1789
+ className: "flex items-start w-full overflow-x-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden pb-1",
1790
+ children: steps.map((step, index) => {
1791
+ const isCompleted = index < currentStep;
1792
+ const isActive = index === currentStep;
1793
+ const isClickable = isCompleted && !!onStepClick;
1794
+ const isLast = index === steps.length - 1;
1795
+ return /* @__PURE__ */ jsxs(React3.Fragment, { children: [
1796
+ /* @__PURE__ */ jsx(
1797
+ "div",
1798
+ {
1799
+ ref: isActive ? activeRef : void 0,
1800
+ role: "listitem",
1801
+ "aria-current": isActive ? "step" : void 0,
1802
+ className: cn("flex flex-col items-center text-center shrink-0"),
1803
+ style: { minWidth: variant === "compact" ? 48 : 64 },
1804
+ children: /* @__PURE__ */ jsxs(
1805
+ "button",
1806
+ {
1807
+ type: "button",
1808
+ disabled: !isClickable,
1809
+ onClick: () => isClickable && onStepClick(index),
1810
+ className: cn(
1811
+ "flex flex-col items-center gap-1.5 group",
1812
+ isClickable ? "cursor-pointer" : "cursor-default"
1813
+ ),
1814
+ children: [
1815
+ /* @__PURE__ */ jsx(
1816
+ StepCircle,
1817
+ {
1818
+ index,
1819
+ isCompleted,
1820
+ isActive,
1821
+ icon: step.icon,
1822
+ variant
1823
+ }
1824
+ ),
1825
+ /* @__PURE__ */ jsxs("div", { className: "max-w-[5.5rem] sm:max-w-[7rem]", children: [
1826
+ /* @__PURE__ */ jsx(
1827
+ "p",
1828
+ {
1829
+ className: cn(
1830
+ "text-xs font-medium leading-tight truncate",
1831
+ isActive || isCompleted ? "text-foreground" : "text-muted-foreground"
1832
+ ),
1833
+ children: step.label
1834
+ }
1835
+ ),
1836
+ step.optional && /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground font-normal", children: "optional" }),
1837
+ step.description && variant !== "compact" && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 leading-tight truncate hidden sm:block", children: step.description })
1838
+ ] })
1839
+ ]
1840
+ }
1841
+ )
1842
+ }
1843
+ ),
1844
+ !isLast && /* @__PURE__ */ jsx(StepConnector, { isCompleted, isVertical: false })
1845
+ ] }, step.label);
1846
+ })
1847
+ }
1848
+ );
1849
+ }
1850
+ function VerticalStepper({
1851
+ steps,
1852
+ currentStep,
1853
+ variant,
1854
+ onStepClick
1855
+ }) {
1856
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Progress", role: "list", className: "flex flex-col", children: steps.map((step, index) => {
1857
+ const isCompleted = index < currentStep;
1858
+ const isActive = index === currentStep;
1859
+ const isClickable = isCompleted && !!onStepClick;
1860
+ const isLast = index === steps.length - 1;
1861
+ return /* @__PURE__ */ jsxs(React3.Fragment, { children: [
1862
+ /* @__PURE__ */ jsx(
1863
+ "div",
1864
+ {
1865
+ role: "listitem",
1866
+ "aria-current": isActive ? "step" : void 0,
1867
+ className: "flex items-start gap-3",
1868
+ children: /* @__PURE__ */ jsxs(
1869
+ "button",
1870
+ {
1871
+ type: "button",
1872
+ disabled: !isClickable,
1873
+ onClick: () => isClickable && onStepClick(index),
1874
+ className: cn(
1875
+ "flex items-center gap-3",
1876
+ isClickable ? "cursor-pointer" : "cursor-default"
1877
+ ),
1878
+ children: [
1879
+ /* @__PURE__ */ jsx(
1880
+ StepCircle,
1881
+ {
1882
+ index,
1883
+ isCompleted,
1884
+ isActive,
1885
+ icon: step.icon,
1886
+ variant
1887
+ }
1888
+ ),
1889
+ /* @__PURE__ */ jsxs("div", { className: "text-left", children: [
1890
+ /* @__PURE__ */ jsxs(
1891
+ "p",
1892
+ {
1893
+ className: cn(
1894
+ "text-sm font-medium leading-tight",
1895
+ isActive || isCompleted ? "text-foreground" : "text-muted-foreground"
1896
+ ),
1897
+ children: [
1898
+ step.label,
1899
+ step.optional && /* @__PURE__ */ jsx("span", { className: "ml-1 text-xs text-muted-foreground font-normal", children: "(optional)" })
1900
+ ]
1901
+ }
1902
+ ),
1903
+ step.description && variant !== "compact" && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5", children: step.description })
1904
+ ] })
1905
+ ]
1906
+ }
1907
+ )
1908
+ }
1909
+ ),
1910
+ !isLast && /* @__PURE__ */ jsx(StepConnector, { isCompleted, isVertical: true })
1911
+ ] }, step.label);
1912
+ }) });
1913
+ }
1914
+ function Stepper({
1915
+ steps,
1916
+ currentStep,
1917
+ variant = "default",
1918
+ orientation = "horizontal",
1919
+ className,
1920
+ onStepClick,
1921
+ children,
1922
+ ...props
1923
+ }) {
1924
+ const normalizedSteps = steps.map(normalizeStep);
1925
+ const isVertical = orientation === "vertical";
1926
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), ...props, children: [
1927
+ isVertical ? /* @__PURE__ */ jsx(
1928
+ VerticalStepper,
1929
+ {
1930
+ steps: normalizedSteps,
1931
+ currentStep,
1932
+ variant,
1933
+ onStepClick
1934
+ }
1935
+ ) : /* @__PURE__ */ jsx(
1936
+ HorizontalStepper,
1937
+ {
1938
+ steps: normalizedSteps,
1939
+ currentStep,
1940
+ variant,
1941
+ onStepClick
1942
+ }
1943
+ ),
1944
+ children && /* @__PURE__ */ jsx("div", { className: cn("mt-6", isVertical && "ml-11"), children })
1945
+ ] });
1946
+ }
1947
+ function StepContent({
1948
+ step,
1949
+ currentStep,
1950
+ children,
1951
+ className,
1952
+ keepMounted = false
1953
+ }) {
1954
+ const isActive = step === currentStep;
1955
+ if (!isActive && !keepMounted) return null;
1956
+ return /* @__PURE__ */ jsx(
1957
+ "div",
1958
+ {
1959
+ className: cn(className),
1960
+ hidden: !isActive,
1961
+ role: "tabpanel",
1962
+ "aria-label": `Step ${step + 1}`,
1963
+ children
1964
+ }
1965
+ );
1966
+ }
1967
+ async function copyToClipboard(text, options) {
1968
+ try {
1969
+ await navigator.clipboard.writeText(text);
1970
+ return true;
1971
+ } catch {
1972
+ return false;
1973
+ }
1974
+ }
1975
+ function CopyButton({
1976
+ value,
1977
+ className,
1978
+ size = "sm",
1979
+ variant = "ghost",
1980
+ showToast = true,
1981
+ toastMessage = "Copied to clipboard",
1982
+ errorMessage = "Failed to copy to clipboard",
1983
+ timeout = 2e3,
1984
+ children,
1985
+ ...props
1986
+ }) {
1987
+ const [copied, setCopied] = useState(false);
1988
+ const handleCopy = async () => {
1989
+ if (!value) return;
1990
+ const success = await copyToClipboard(value);
1991
+ if (success) {
1992
+ setCopied(true);
1993
+ setTimeout(() => setCopied(false), timeout);
1994
+ }
1995
+ };
1996
+ return /* @__PURE__ */ jsx(
1997
+ Button,
1998
+ {
1999
+ variant,
2000
+ size,
2001
+ className: cn("h-6 w-6 p-0", className),
2002
+ onClick: handleCopy,
2003
+ disabled: !value,
2004
+ ...props,
2005
+ children: children || (copied ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3" }))
2006
+ }
2007
+ );
2008
+ }
2009
+ function CopyText({
2010
+ value,
2011
+ displayValue,
2012
+ className,
2013
+ textClassName,
2014
+ buttonClassName,
2015
+ maxLength = 30,
2016
+ showButton = true,
2017
+ ...buttonProps
2018
+ }) {
2019
+ const truncatedValue = displayValue || (value && value.length > maxLength ? `${value.substring(0, maxLength)}...` : value || "N/A");
2020
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
2021
+ /* @__PURE__ */ jsx("span", { className: cn("font-medium", textClassName), title: value || "N/A", children: truncatedValue }),
2022
+ showButton && value && /* @__PURE__ */ jsx(CopyButton, { value, className: buttonClassName, ...buttonProps })
2023
+ ] });
2024
+ }
2025
+ function CopyCodeBlock({
2026
+ value,
2027
+ className,
2028
+ language,
2029
+ showLineNumbers = false,
2030
+ ...buttonProps
2031
+ }) {
2032
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative group", className), children: [
2033
+ /* @__PURE__ */ jsx("pre", { className: "bg-muted p-4 rounded-md overflow-x-auto text-sm", children: /* @__PURE__ */ jsx("code", { className: language ? `language-${language}` : "", children: value }) }),
2034
+ /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx(CopyButton, { value, variant: "secondary", size: "sm", ...buttonProps }) })
2035
+ ] });
2036
+ }
2037
+ var ScrollButton = React3__default.memo(function ScrollButton2({ direction, onClick, visible, className }) {
2038
+ if (!visible) return null;
2039
+ const handleClick = (e) => {
2040
+ e.preventDefault();
2041
+ e.stopPropagation();
2042
+ onClick();
2043
+ };
2044
+ return /* @__PURE__ */ jsx(
2045
+ "button",
2046
+ {
2047
+ type: "button",
2048
+ className: cn(
2049
+ "absolute top-1/2 -translate-y-1/2 z-50",
2050
+ "flex items-center justify-center",
2051
+ "size-10 rounded-md shadow-lg border-2 border-border",
2052
+ "bg-background hover:bg-muted",
2053
+ "transition-transform duration-200",
2054
+ "hover:scale-105 active:scale-95",
2055
+ direction === "left" ? "left-2" : "right-2",
2056
+ className
2057
+ ),
2058
+ onClick: handleClick,
2059
+ onMouseDown: (e) => e.stopPropagation(),
2060
+ "aria-label": `Scroll ${direction}`,
2061
+ children: direction === "left" ? /* @__PURE__ */ jsx(ChevronLeft, { className: "size-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-5" })
2062
+ }
2063
+ );
2064
+ });
1412
2065
  function DataTable({
1413
2066
  columns,
1414
2067
  data,
@@ -1417,7 +2070,9 @@ function DataTable({
1417
2070
  enableSorting = false,
1418
2071
  enableRowSelection = false,
1419
2072
  onRowSelectionChange,
1420
- className
2073
+ className,
2074
+ loadingState: customLoadingState,
2075
+ emptyState: customEmptyState
1421
2076
  }) {
1422
2077
  const [sorting, setSorting] = useState([]);
1423
2078
  const [rowSelection, setRowSelection] = useState({});
@@ -1499,14 +2154,14 @@ function DataTable({
1499
2154
  const timer = setTimeout(checkScroll, 150);
1500
2155
  return () => clearTimeout(timer);
1501
2156
  }, [data, checkScroll]);
1502
- const loadingState = useMemo(
2157
+ const defaultLoadingState = useMemo(
1503
2158
  () => /* @__PURE__ */ jsx("div", { className: "w-full h-full min-h-[24rem] flex items-center justify-center bg-background/50 rounded-lg border border-border", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
1504
2159
  /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-2 border-primary border-t-transparent" }),
1505
2160
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading data..." })
1506
2161
  ] }) }),
1507
2162
  []
1508
2163
  );
1509
- const emptyState = useMemo(
2164
+ const defaultEmptyState = useMemo(
1510
2165
  () => /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-32 text-center", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8", children: [
1511
2166
  /* @__PURE__ */ jsx("div", { className: "rounded-full bg-muted p-3 mb-4", children: /* @__PURE__ */ jsx(Search, { className: "h-6 w-6 text-muted-foreground" }) }),
1512
2167
  /* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-foreground mb-1", children: "No results found" }),
@@ -1515,7 +2170,7 @@ function DataTable({
1515
2170
  [columns.length]
1516
2171
  );
1517
2172
  if (isLoading) {
1518
- return loadingState;
2173
+ return /* @__PURE__ */ jsx(Fragment, { children: customLoadingState || defaultLoadingState });
1519
2174
  }
1520
2175
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full gap-4", className), children: [
1521
2176
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 rounded-lg border overflow-hidden bg-background shadow-sm relative", children: [
@@ -1575,7 +2230,7 @@ function DataTable({
1575
2230
  ))
1576
2231
  },
1577
2232
  row.id
1578
- )) : emptyState })
2233
+ )) : customEmptyState ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-32 text-center", children: customEmptyState }) }) : defaultEmptyState })
1579
2234
  ] }) }),
1580
2235
  /* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" })
1581
2236
  ] }),
@@ -1611,12 +2266,12 @@ function DataTable({
1611
2266
  ] });
1612
2267
  }
1613
2268
  var SIZE_VARIANTS = {
1614
- sm: "sm:!max-w-sm",
1615
- default: "sm:!max-w-md",
1616
- lg: "sm:!max-w-lg md:!max-w-2xl",
1617
- xl: "sm:!max-w-2xl md:!max-w-4xl",
1618
- "2xl": "sm:!max-w-4xl md:!max-w-6xl",
1619
- full: "!max-w-[95vw] !h-[95vh]"
2269
+ sm: "sm:max-w-sm",
2270
+ default: "sm:max-w-md",
2271
+ lg: "sm:max-w-lg md:max-w-2xl",
2272
+ xl: "sm:max-w-2xl md:max-w-4xl",
2273
+ "2xl": "sm:max-w-4xl md:max-w-6xl",
2274
+ full: "max-w-[95vw] h-[95vh]"
1620
2275
  };
1621
2276
  function DialogWrapper({
1622
2277
  open,
@@ -1643,7 +2298,7 @@ function DialogWrapper({
1643
2298
  DialogContent,
1644
2299
  {
1645
2300
  showCloseButton: !hideCloseButton,
1646
- className: cn(SIZE_VARIANTS[size], contentClassName, className),
2301
+ className: cn("max-w-none", SIZE_VARIANTS[size], contentClassName, className),
1647
2302
  children: [
1648
2303
  !hideHeader && /* @__PURE__ */ jsxs(DialogHeader, { className: cn("space-y-2", headerClassName), children: [
1649
2304
  hideTitle ? /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: title || "Dialog" }) : /* @__PURE__ */ jsx(DialogTitle, { children: title || "Dialog" }),
@@ -1670,18 +2325,10 @@ function FormDialog({
1670
2325
  submitDisabled = false,
1671
2326
  ...props
1672
2327
  }) {
1673
- const footer = /* @__PURE__ */ jsxs(Fragment, { children: [
1674
- /* @__PURE__ */ jsx(
1675
- Button,
1676
- {
1677
- variant: "outline",
1678
- onClick: onCancel || (() => onOpenChange(false)),
1679
- disabled: isLoading,
1680
- children: cancelText
1681
- }
1682
- ),
1683
- /* @__PURE__ */ jsx(Button, { onClick: onSubmit, disabled: isLoading || submitDisabled, children: isLoading ? "Loading..." : submitText })
1684
- ] });
2328
+ const handleSubmit = (e) => {
2329
+ e.preventDefault();
2330
+ onSubmit?.(e);
2331
+ };
1685
2332
  return /* @__PURE__ */ jsx(
1686
2333
  DialogWrapper,
1687
2334
  {
@@ -1689,16 +2336,30 @@ function FormDialog({
1689
2336
  onOpenChange,
1690
2337
  title,
1691
2338
  description,
1692
- footer,
1693
2339
  ...props,
1694
- children
1695
- }
1696
- );
1697
- }
1698
- function DropdownWrapper({
1699
- trigger,
1700
- children,
1701
- align = "end",
2340
+ children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
2341
+ children,
2342
+ /* @__PURE__ */ jsxs(DialogFooter, { className: "gap-2 mt-4", children: [
2343
+ /* @__PURE__ */ jsx(
2344
+ Button,
2345
+ {
2346
+ type: "button",
2347
+ variant: "outline",
2348
+ onClick: onCancel || (() => onOpenChange(false)),
2349
+ disabled: isLoading,
2350
+ children: cancelText
2351
+ }
2352
+ ),
2353
+ /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isLoading || submitDisabled, children: isLoading ? "Loading..." : submitText })
2354
+ ] })
2355
+ ] })
2356
+ }
2357
+ );
2358
+ }
2359
+ function DropdownWrapper({
2360
+ trigger,
2361
+ children,
2362
+ align = "end",
1702
2363
  side = "bottom",
1703
2364
  sideOffset = 4,
1704
2365
  className,
@@ -1984,11 +2645,11 @@ function RadioDropdown({
1984
2645
  )
1985
2646
  ] });
1986
2647
  }
1987
- function InfoRow({ label, value, copyable = false, icon: Icon2 }) {
2648
+ function InfoRow({ label, value, copyable = false, icon: Icon }) {
1988
2649
  if (!value && value !== 0) return null;
1989
2650
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-center py-3 gap-2 group hover:bg-muted rounded-md px-3 -mx-3 transition-colors", children: [
1990
2651
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
1991
- Icon2 && /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 text-muted-foreground flex-shrink-0" }),
2652
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground flex-shrink-0" }),
1992
2653
  /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-muted-foreground truncate", children: label })
1993
2654
  ] }),
1994
2655
  /* @__PURE__ */ jsx("div", { className: "sm:text-right min-w-0 flex-shrink-0", children: copyable ? /* @__PURE__ */ jsx(
@@ -2033,7 +2694,7 @@ var iconItemMediaVariants = cva(
2033
2694
  }
2034
2695
  }
2035
2696
  );
2036
- var IconItemMedia = React5.memo(function IconItemMedia2({
2697
+ var IconItemMedia = React3.memo(function IconItemMedia2({
2037
2698
  icon,
2038
2699
  iconBg = "primary",
2039
2700
  iconSize = "md",
@@ -2053,7 +2714,7 @@ var IconItemMedia = React5.memo(function IconItemMedia2({
2053
2714
  );
2054
2715
  });
2055
2716
  IconItemMedia.displayName = "IconItemMedia";
2056
- var FeatureItem = React5.memo(function FeatureItem2({
2717
+ var FeatureItem = React3.memo(function FeatureItem2({
2057
2718
  icon,
2058
2719
  iconBg = "primary",
2059
2720
  iconSize = "md",
@@ -2095,7 +2756,10 @@ var FeatureItem = React5.memo(function FeatureItem2({
2095
2756
  icon,
2096
2757
  iconBg,
2097
2758
  iconSize,
2098
- className: cn(layout === "vertical" ? "" : "shrink-0", iconClassName)
2759
+ className: cn(
2760
+ layout === "vertical" ? "" : "shrink-0",
2761
+ iconClassName
2762
+ )
2099
2763
  }
2100
2764
  ),
2101
2765
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 flex-1", children: [
@@ -2173,10 +2837,50 @@ var FeatureItem = React5.memo(function FeatureItem2({
2173
2837
  );
2174
2838
  });
2175
2839
  FeatureItem.displayName = "FeatureItem";
2840
+ function FeatureList({
2841
+ items = [],
2842
+ columns = 3,
2843
+ variant = "outline",
2844
+ iconBg = "primary",
2845
+ iconSize = "md",
2846
+ layout = "vertical",
2847
+ className,
2848
+ itemClassName,
2849
+ ...props
2850
+ }) {
2851
+ const gridCols = {
2852
+ 2: "md:grid-cols-2",
2853
+ 3: "md:grid-cols-2 lg:grid-cols-3",
2854
+ 4: "md:grid-cols-2 lg:grid-cols-4"
2855
+ };
2856
+ return /* @__PURE__ */ jsx(
2857
+ "div",
2858
+ {
2859
+ role: "list",
2860
+ className: cn("grid gap-6", gridCols[columns] || gridCols[3], className),
2861
+ ...props,
2862
+ children: items.map((item, index) => /* @__PURE__ */ jsx(
2863
+ FeatureItem,
2864
+ {
2865
+ icon: item.icon,
2866
+ iconBg: item.iconBg || iconBg,
2867
+ iconSize: item.iconSize || iconSize,
2868
+ title: item.title,
2869
+ description: item.description,
2870
+ variant,
2871
+ layout,
2872
+ className: itemClassName
2873
+ },
2874
+ item.id || item.title || index
2875
+ ))
2876
+ }
2877
+ );
2878
+ }
2879
+ FeatureList.displayName = "FeatureList";
2176
2880
  function ModeToggle() {
2177
2881
  const { theme, setTheme } = useTheme();
2178
- const [mounted, setMounted] = React5.useState(false);
2179
- React5.useEffect(() => {
2882
+ const [mounted, setMounted] = React3.useState(false);
2883
+ React3.useEffect(() => {
2180
2884
  setMounted(true);
2181
2885
  }, []);
2182
2886
  if (!mounted) {
@@ -2198,7 +2902,7 @@ function ModeToggle() {
2198
2902
  ] }) })
2199
2903
  ] });
2200
2904
  }
2201
- var COUNTRIES = [
2905
+ var DEFAULT_COUNTRIES = [
2202
2906
  { code: "GB", name: "United Kingdom", dialCode: "+44", flag: "\u{1F1EC}\u{1F1E7}" },
2203
2907
  { code: "US", name: "United States", dialCode: "+1", flag: "\u{1F1FA}\u{1F1F8}" },
2204
2908
  { code: "IE", name: "Ireland", dialCode: "+353", flag: "\u{1F1EE}\u{1F1EA}" },
@@ -2250,145 +2954,147 @@ var COUNTRIES = [
2250
2954
  { code: "RU", name: "Russia", dialCode: "+7", flag: "\u{1F1F7}\u{1F1FA}" },
2251
2955
  { code: "IL", name: "Israel", dialCode: "+972", flag: "\u{1F1EE}\u{1F1F1}" }
2252
2956
  ];
2253
- var getCountryByCode = (code) => COUNTRIES.find((c) => c.code === code);
2254
- var PhoneInput = React5.forwardRef(
2255
- ({
2256
- className,
2257
- onChange,
2258
- value,
2259
- defaultCountry = "GB",
2260
- disabled,
2261
- placeholder = "Phone number",
2262
- ...props
2263
- }, ref) => {
2264
- const [isOpen, setIsOpen] = React5.useState(false);
2265
- const [searchValue, setSearchValue] = React5.useState("");
2266
- const parseValue = React5.useCallback(
2267
- (val) => {
2268
- const valString = val ? String(val) : "";
2269
- if (!valString) {
2270
- return {
2271
- country: getCountryByCode(defaultCountry) || COUNTRIES[0],
2272
- number: ""
2273
- };
2274
- }
2275
- const cleanVal = valString.replace(/\s/g, "");
2276
- for (const country2 of COUNTRIES) {
2277
- if (cleanVal.startsWith(country2.dialCode)) {
2278
- return {
2279
- country: country2,
2280
- number: cleanVal.slice(country2.dialCode.length)
2281
- };
2282
- }
2283
- }
2957
+ function PhoneInput({
2958
+ className,
2959
+ onChange,
2960
+ value,
2961
+ defaultCountry = "GB",
2962
+ countries = DEFAULT_COUNTRIES,
2963
+ disabled,
2964
+ placeholder = "Phone number",
2965
+ ref,
2966
+ ...props
2967
+ }) {
2968
+ const [isOpen, setIsOpen] = React3.useState(false);
2969
+ const [searchValue, setSearchValue] = React3.useState("");
2970
+ const getCountryByCode = React3.useCallback(
2971
+ (code) => countries.find((c) => c.code === code),
2972
+ [countries]
2973
+ );
2974
+ const parseValue = React3.useCallback(
2975
+ (val) => {
2976
+ const valString = val ? String(val) : "";
2977
+ if (!valString) {
2284
2978
  return {
2285
- country: getCountryByCode(defaultCountry) || COUNTRIES[0],
2286
- number: cleanVal.replace(/^\+/, "")
2979
+ country: getCountryByCode(defaultCountry) || countries[0],
2980
+ number: ""
2287
2981
  };
2288
- },
2289
- [defaultCountry]
2290
- );
2291
- const { country, number } = parseValue(value);
2292
- const [selectedCountry, setSelectedCountry] = React5.useState(country);
2293
- React5.useEffect(() => {
2294
- const parsed = parseValue(value);
2295
- setSelectedCountry(parsed.country);
2296
- }, [value, parseValue]);
2297
- const handleCountryChange = (newCountry) => {
2298
- setSelectedCountry(newCountry);
2299
- setIsOpen(false);
2300
- if (number) {
2301
- onChange?.(newCountry.dialCode + number);
2302
2982
  }
2303
- };
2304
- const handleNumberChange = (e) => {
2305
- const newNumber = e.target.value.replace(/[^\d]/g, "");
2306
- if (newNumber) {
2307
- onChange?.(selectedCountry.dialCode + newNumber);
2308
- } else {
2309
- onChange?.("");
2983
+ const cleanVal = valString.replace(/\s/g, "");
2984
+ for (const country2 of countries) {
2985
+ if (cleanVal.startsWith(country2.dialCode)) {
2986
+ return {
2987
+ country: country2,
2988
+ number: cleanVal.slice(country2.dialCode.length)
2989
+ };
2990
+ }
2310
2991
  }
2311
- };
2312
- return /* @__PURE__ */ jsxs(InputGroup, { className, children: [
2313
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(
2314
- Popover,
2315
- {
2316
- open: isOpen,
2317
- modal: true,
2318
- onOpenChange: (open) => {
2319
- setIsOpen(open);
2320
- if (open) setSearchValue("");
2321
- },
2322
- children: [
2992
+ return {
2993
+ country: getCountryByCode(defaultCountry) || countries[0],
2994
+ number: cleanVal.replace(/^\+/, "")
2995
+ };
2996
+ },
2997
+ [defaultCountry, countries, getCountryByCode]
2998
+ );
2999
+ const { country, number } = parseValue(value);
3000
+ const [selectedCountry, setSelectedCountry] = React3.useState(country);
3001
+ React3.useEffect(() => {
3002
+ const parsed = parseValue(value);
3003
+ setSelectedCountry(parsed.country);
3004
+ }, [value, parseValue]);
3005
+ const handleCountryChange = (newCountry) => {
3006
+ setSelectedCountry(newCountry);
3007
+ setIsOpen(false);
3008
+ if (number) {
3009
+ onChange?.(newCountry.dialCode + number);
3010
+ }
3011
+ };
3012
+ const handleNumberChange = (e) => {
3013
+ const newNumber = e.target.value.replace(/[^\d]/g, "");
3014
+ if (newNumber) {
3015
+ onChange?.(selectedCountry.dialCode + newNumber);
3016
+ } else {
3017
+ onChange?.("");
3018
+ }
3019
+ };
3020
+ return /* @__PURE__ */ jsxs(InputGroup, { className, children: [
3021
+ /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(
3022
+ Popover,
3023
+ {
3024
+ open: isOpen,
3025
+ modal: true,
3026
+ onOpenChange: (open) => {
3027
+ setIsOpen(open);
3028
+ if (open) setSearchValue("");
3029
+ },
3030
+ children: [
3031
+ /* @__PURE__ */ jsx(
3032
+ PopoverTrigger,
3033
+ {
3034
+ render: /* @__PURE__ */ jsxs(
3035
+ Button,
3036
+ {
3037
+ type: "button",
3038
+ variant: "ghost",
3039
+ className: "gap-1.5 rounded-none border-r px-3 focus:z-10 min-w-[90px] h-full",
3040
+ disabled,
3041
+ children: [
3042
+ /* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: selectedCountry.flag }),
3043
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: selectedCountry.dialCode }),
3044
+ /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-50" })
3045
+ ]
3046
+ }
3047
+ )
3048
+ }
3049
+ ),
3050
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-[280px] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
2323
3051
  /* @__PURE__ */ jsx(
2324
- PopoverTrigger,
3052
+ CommandInput,
2325
3053
  {
2326
- render: /* @__PURE__ */ jsxs(
2327
- Button,
2328
- {
2329
- type: "button",
2330
- variant: "ghost",
2331
- className: "gap-1.5 rounded-none border-r px-3 focus:z-10 min-w-[90px] h-full",
2332
- disabled,
2333
- children: [
2334
- /* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: selectedCountry.flag }),
2335
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: selectedCountry.dialCode }),
2336
- /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-50" })
2337
- ]
2338
- }
2339
- )
3054
+ value: searchValue,
3055
+ onValueChange: setSearchValue,
3056
+ placeholder: "Search country..."
2340
3057
  }
2341
3058
  ),
2342
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[280px] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
2343
- /* @__PURE__ */ jsx(
2344
- CommandInput,
3059
+ /* @__PURE__ */ jsx(CommandList, { children: /* @__PURE__ */ jsxs(ScrollArea, { className: "h-64", children: [
3060
+ /* @__PURE__ */ jsx(CommandEmpty, { children: "No country found." }),
3061
+ /* @__PURE__ */ jsx(CommandGroup, { children: countries.filter(
3062
+ (c) => c.name.toLowerCase().includes(searchValue.toLowerCase()) || c.dialCode.includes(searchValue) || c.code.toLowerCase().includes(searchValue.toLowerCase())
3063
+ ).map((c) => /* @__PURE__ */ jsxs(
3064
+ CommandItem,
2345
3065
  {
2346
- value: searchValue,
2347
- onValueChange: setSearchValue,
2348
- placeholder: "Search country..."
2349
- }
2350
- ),
2351
- /* @__PURE__ */ jsx(CommandList, { children: /* @__PURE__ */ jsxs(ScrollArea, { className: "h-64", children: [
2352
- /* @__PURE__ */ jsx(CommandEmpty, { children: "No country found." }),
2353
- /* @__PURE__ */ jsx(CommandGroup, { children: COUNTRIES.filter(
2354
- (c) => c.name.toLowerCase().includes(searchValue.toLowerCase()) || c.dialCode.includes(searchValue) || c.code.toLowerCase().includes(searchValue.toLowerCase())
2355
- ).map((c) => /* @__PURE__ */ jsxs(
2356
- CommandItem,
2357
- {
2358
- className: "gap-2 cursor-pointer",
2359
- onSelect: () => handleCountryChange(c),
2360
- value: `${c.name} ${c.code} ${c.dialCode}`,
2361
- children: [
2362
- /* @__PURE__ */ jsx("span", { className: "text-base", children: c.flag }),
2363
- /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm", children: c.name }),
2364
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: c.dialCode })
2365
- ]
2366
- },
2367
- c.code
2368
- )) })
2369
- ] }) })
3066
+ className: "gap-2 cursor-pointer",
3067
+ onSelect: () => handleCountryChange(c),
3068
+ value: `${c.name} ${c.code} ${c.dialCode}`,
3069
+ children: [
3070
+ /* @__PURE__ */ jsx("span", { className: "text-base", children: c.flag }),
3071
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm", children: c.name }),
3072
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: c.dialCode })
3073
+ ]
3074
+ },
3075
+ c.code
3076
+ )) })
2370
3077
  ] }) })
2371
- ]
2372
- }
2373
- ) }),
2374
- /* @__PURE__ */ jsx(
2375
- InputGroupInput,
2376
- {
2377
- ref,
2378
- type: "tel",
2379
- inputMode: "numeric",
2380
- className: "rounded-s-none",
2381
- placeholder,
2382
- value: number,
2383
- onChange: handleNumberChange,
2384
- disabled,
2385
- ...props
2386
- }
2387
- )
2388
- ] });
2389
- }
2390
- );
2391
- PhoneInput.displayName = "PhoneInput";
3078
+ ] }) })
3079
+ ]
3080
+ }
3081
+ ) }),
3082
+ /* @__PURE__ */ jsx(
3083
+ InputGroupInput,
3084
+ {
3085
+ ref,
3086
+ type: "tel",
3087
+ inputMode: "numeric",
3088
+ className: "rounded-s-none",
3089
+ placeholder,
3090
+ value: number,
3091
+ onChange: handleNumberChange,
3092
+ disabled,
3093
+ ...props
3094
+ }
3095
+ )
3096
+ ] });
3097
+ }
2392
3098
  function Pill({
2393
3099
  variant = "secondary",
2394
3100
  themed = false,
@@ -2468,8 +3174,8 @@ function PillDelta({ className, delta }) {
2468
3174
  }
2469
3175
  return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-3 text-rose-500", className) });
2470
3176
  }
2471
- function PillIcon({ icon: Icon2, className, ...props }) {
2472
- return /* @__PURE__ */ jsx(Icon2, { className: cn("size-3 text-muted-foreground", className), size: 12, ...props });
3177
+ function PillIcon({ icon: Icon, className, ...props }) {
3178
+ return /* @__PURE__ */ jsx(Icon, { className: cn("size-3 text-muted-foreground", className), size: 12, ...props });
2473
3179
  }
2474
3180
  function PillAvatarGroup({ children, className, ...props }) {
2475
3181
  return /* @__PURE__ */ jsx(
@@ -2602,7 +3308,16 @@ var TabContent = memo(function TabContent2({
2602
3308
  () => cn(padding && "px-6 py-4"),
2603
3309
  [padding]
2604
3310
  );
2605
- return /* @__PURE__ */ jsx(TabsContent, { value, keepMounted, className: contentClassName, ...props, children: withScrollArea ? /* @__PURE__ */ jsx(ScrollArea, { className: cn("h-full", scrollAreaClassName), children: /* @__PURE__ */ jsx("div", { className: scrollAreaPaddingClassName, children }) }) : children });
3311
+ return /* @__PURE__ */ jsx(
3312
+ TabsContent,
3313
+ {
3314
+ value,
3315
+ keepMounted,
3316
+ className: contentClassName,
3317
+ ...props,
3318
+ children: withScrollArea ? /* @__PURE__ */ jsx(ScrollArea, { className: cn("h-full", scrollAreaClassName), children: /* @__PURE__ */ jsx("div", { className: scrollAreaPaddingClassName, children }) }) : children
3319
+ }
3320
+ );
2606
3321
  });
2607
3322
  var DynamicTabs = memo(function DynamicTabs2({
2608
3323
  tabs = [],
@@ -2860,203 +3575,6 @@ function ResponsiveSplitLayout({
2860
3575
  }
2861
3576
  );
2862
3577
  }
2863
- var SIZE_VARIANTS2 = {
2864
- sm: "sm:!max-w-md",
2865
- default: "w-full sm:!max-w-md md:!max-w-lg",
2866
- lg: "w-full sm:!max-w-lg md:!max-w-2xl lg:!max-w-4xl",
2867
- xl: "w-full sm:!max-w-2xl md:!max-w-4xl lg:!max-w-5xl",
2868
- full: "w-full !max-w-full",
2869
- mobile: "w-[85%] !max-w-sm",
2870
- "mobile-nav": "!w-[300px] sm:!w-[350px]"
2871
- };
2872
- var getPadding = (size, type = "default") => {
2873
- const isFullSize = size === "full";
2874
- if (type === "header" || type === "footer") {
2875
- return isFullSize ? "px-6 lg:px-8" : "px-4";
2876
- }
2877
- return isFullSize ? "p-6 lg:p-8" : "p-4";
2878
- };
2879
- var SheetWrapper = memo(function SheetWrapper2({
2880
- open,
2881
- onOpenChange,
2882
- title,
2883
- description,
2884
- children,
2885
- footer,
2886
- header,
2887
- side = "right",
2888
- size = "default",
2889
- modal = true,
2890
- className,
2891
- headerClassName,
2892
- contentClassName,
2893
- footerClassName,
2894
- innerClassName,
2895
- hideHeader = false,
2896
- hideTitle = false,
2897
- hideDescription = false,
2898
- hideCloseButton = false,
2899
- disableContentPadding = false
2900
- }) {
2901
- const computedClasses = useMemo(
2902
- () => ({
2903
- header: cn("border-b pb-4 pt-6", getPadding(size, "header"), headerClassName),
2904
- inner: cn(
2905
- "flex-1 overflow-y-auto",
2906
- !disableContentPadding && getPadding(size),
2907
- innerClassName
2908
- ),
2909
- footer: cn(
2910
- "border-t bg-muted/30 pt-4 pb-6 mt-auto",
2911
- getPadding(size, "footer"),
2912
- footerClassName
2913
- )
2914
- }),
2915
- [size, headerClassName, innerClassName, footerClassName, disableContentPadding]
2916
- );
2917
- const shouldHideTitle = !!header || hideTitle;
2918
- const shouldHideDescription = !!header || hideDescription;
2919
- return /* @__PURE__ */ jsx(Sheet, { open, onOpenChange, modal, children: /* @__PURE__ */ jsxs(
2920
- SheetContent,
2921
- {
2922
- side,
2923
- showCloseButton: !hideCloseButton,
2924
- className: cn(SIZE_VARIANTS2[size], "flex flex-col p-0", contentClassName, className),
2925
- children: [
2926
- !hideHeader && /* @__PURE__ */ jsxs(SheetHeader, { className: computedClasses.header, children: [
2927
- /* @__PURE__ */ jsx(SheetTitle, { className: shouldHideTitle ? "sr-only" : "", children: title || "Sheet" }),
2928
- description && /* @__PURE__ */ jsx(SheetDescription, { className: shouldHideDescription ? "sr-only" : "", children: description }),
2929
- header
2930
- ] }),
2931
- /* @__PURE__ */ jsx("div", { className: computedClasses.inner, children }),
2932
- footer && /* @__PURE__ */ jsx(SheetFooter, { className: computedClasses.footer, children: footer })
2933
- ]
2934
- }
2935
- ) });
2936
- });
2937
- var FormSheet = memo(function FormSheet2({
2938
- open,
2939
- onOpenChange,
2940
- title,
2941
- description,
2942
- children,
2943
- onSubmit,
2944
- onCancel,
2945
- submitLabel = "Submit",
2946
- cancelLabel = "Cancel",
2947
- submitDisabled = false,
2948
- submitLoading = false,
2949
- formId,
2950
- size = "lg",
2951
- ...props
2952
- }) {
2953
- const handleCancel = useCallback(() => {
2954
- onCancel?.();
2955
- onOpenChange?.(false);
2956
- }, [onCancel, onOpenChange]);
2957
- const footer = useMemo(
2958
- () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-2 w-full", children: [
2959
- /* @__PURE__ */ jsx(
2960
- Button,
2961
- {
2962
- type: "button",
2963
- variant: "outline",
2964
- className: "flex-1",
2965
- onClick: handleCancel,
2966
- disabled: submitDisabled || submitLoading,
2967
- children: cancelLabel
2968
- }
2969
- ),
2970
- /* @__PURE__ */ jsx(
2971
- ClientSubmitButton,
2972
- {
2973
- form: formId,
2974
- className: "flex-1",
2975
- disabled: submitDisabled,
2976
- loading: submitLoading,
2977
- loadingText: "Saving...",
2978
- children: submitLabel
2979
- }
2980
- )
2981
- ] }),
2982
- [cancelLabel, submitLabel, submitDisabled, submitLoading, formId, handleCancel]
2983
- );
2984
- return /* @__PURE__ */ jsx(
2985
- SheetWrapper,
2986
- {
2987
- open,
2988
- onOpenChange,
2989
- title,
2990
- description,
2991
- size,
2992
- footer,
2993
- ...props,
2994
- children
2995
- }
2996
- );
2997
- });
2998
- var ConfirmSheet = memo(function ConfirmSheet2({
2999
- open,
3000
- onOpenChange,
3001
- title = "Confirm Action",
3002
- description,
3003
- children,
3004
- onConfirm,
3005
- onCancel,
3006
- confirmLabel = "Confirm",
3007
- cancelLabel = "Cancel",
3008
- confirmVariant = "default",
3009
- confirmDisabled = false,
3010
- confirmLoading = false,
3011
- size = "sm",
3012
- ...props
3013
- }) {
3014
- const handleConfirm = useCallback(() => {
3015
- onConfirm?.();
3016
- }, [onConfirm]);
3017
- const handleCancel = useCallback(() => {
3018
- onCancel?.();
3019
- onOpenChange?.(false);
3020
- }, [onCancel, onOpenChange]);
3021
- const footer = useMemo(
3022
- () => /* @__PURE__ */ jsxs("div", { className: "flex gap-2 w-full", children: [
3023
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", className: "flex-1", onClick: handleCancel, children: cancelLabel }),
3024
- /* @__PURE__ */ jsx(
3025
- Button,
3026
- {
3027
- type: "button",
3028
- variant: confirmVariant,
3029
- className: "flex-1",
3030
- onClick: handleConfirm,
3031
- disabled: confirmDisabled || confirmLoading,
3032
- children: confirmLoading ? "Loading..." : confirmLabel
3033
- }
3034
- )
3035
- ] }),
3036
- [
3037
- cancelLabel,
3038
- confirmLabel,
3039
- confirmVariant,
3040
- confirmDisabled,
3041
- confirmLoading,
3042
- handleConfirm,
3043
- handleCancel
3044
- ]
3045
- );
3046
- return /* @__PURE__ */ jsx(
3047
- SheetWrapper,
3048
- {
3049
- open,
3050
- onOpenChange,
3051
- title,
3052
- description,
3053
- size,
3054
- footer,
3055
- ...props,
3056
- children
3057
- }
3058
- );
3059
- });
3060
3578
  function TableWrapper({
3061
3579
  title,
3062
3580
  description,
@@ -3239,12 +3757,6 @@ function FormInput({
3239
3757
  labelClassName,
3240
3758
  inputClassName,
3241
3759
  inputGroupClassName,
3242
- // PascalCase variants
3243
- IconLeft,
3244
- IconRight,
3245
- AddonLeft,
3246
- AddonRight,
3247
- // camelCase variants
3248
3760
  iconLeft,
3249
3761
  iconRight,
3250
3762
  addonLeft,
@@ -3264,10 +3776,6 @@ function FormInput({
3264
3776
  inputMode,
3265
3777
  enterKeyHint
3266
3778
  }) {
3267
- const resolvedIconLeft = IconLeft || iconLeft;
3268
- const resolvedIconRight = IconRight || iconRight;
3269
- const resolvedAddonLeft = AddonLeft || addonLeft;
3270
- const resolvedAddonRight = AddonRight || addonRight;
3271
3779
  const descriptionText = description || helperText;
3272
3780
  const handleChange = (e, field) => {
3273
3781
  const newValue = transform?.output ? transform.output(e.target.value) : e.target.value;
@@ -3278,7 +3786,7 @@ function FormInput({
3278
3786
  }
3279
3787
  onValueChange?.(newValue);
3280
3788
  };
3281
- const hasInputGroup = resolvedIconLeft || resolvedIconRight || resolvedAddonLeft || resolvedAddonRight;
3789
+ const hasInputGroup = iconLeft || iconRight || addonLeft || addonRight;
3282
3790
  const renderInput = (field, isDisabled, fieldState) => {
3283
3791
  const rawValue = field ? transform?.input ? transform.input(field.value) : field.value : transform?.input ? transform.input(value) : value;
3284
3792
  const safeValue = rawValue ?? "";
@@ -3314,9 +3822,9 @@ function FormInput({
3314
3822
  className: cn(inputGroupClassName),
3315
3823
  "data-disabled": isDisabled,
3316
3824
  children: [
3317
- (resolvedAddonLeft || resolvedIconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: resolvedAddonLeft || resolvedIconLeft }),
3825
+ (addonLeft || iconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: addonLeft || iconLeft }),
3318
3826
  /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps, className: inputClassName }),
3319
- (resolvedAddonRight || resolvedIconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: resolvedAddonRight || resolvedIconRight })
3827
+ (addonRight || iconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: addonRight || iconRight })
3320
3828
  ]
3321
3829
  }
3322
3830
  );
@@ -3375,12 +3883,6 @@ function FormTextarea({
3375
3883
  labelClassName,
3376
3884
  textareaClassName,
3377
3885
  inputGroupClassName,
3378
- // PascalCase variants
3379
- IconLeft,
3380
- IconRight,
3381
- AddonLeft,
3382
- AddonRight,
3383
- // camelCase variants
3384
3886
  iconLeft,
3385
3887
  iconRight,
3386
3888
  addonLeft,
@@ -3391,12 +3893,8 @@ function FormTextarea({
3391
3893
  autoComplete,
3392
3894
  autoFocus
3393
3895
  }) {
3394
- const resolvedIconLeft = IconLeft || iconLeft;
3395
- const resolvedIconRight = IconRight || iconRight;
3396
- const resolvedAddonLeft = AddonLeft || addonLeft;
3397
- const resolvedAddonRight = AddonRight || addonRight;
3398
3896
  const descriptionText = description || helperText;
3399
- const hasInputGroup = resolvedIconLeft || resolvedIconRight || resolvedAddonLeft || resolvedAddonRight;
3897
+ const hasInputGroup = iconLeft || iconRight || addonLeft || addonRight;
3400
3898
  const [localValue, setLocalValue] = useState(propValue || "");
3401
3899
  useEffect(() => {
3402
3900
  if (propValue !== void 0) {
@@ -3445,7 +3943,7 @@ function FormTextarea({
3445
3943
  className: cn(inputGroupClassName),
3446
3944
  "data-disabled": isDisabled,
3447
3945
  children: [
3448
- (resolvedAddonLeft || resolvedIconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: resolvedAddonLeft || resolvedIconLeft }),
3946
+ (addonLeft || iconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: addonLeft || iconLeft }),
3449
3947
  /* @__PURE__ */ jsx(
3450
3948
  InputGroupTextarea,
3451
3949
  {
@@ -3453,7 +3951,7 @@ function FormTextarea({
3453
3951
  className: cn("overflow-auto resize-none", textareaClassName)
3454
3952
  }
3455
3953
  ),
3456
- (resolvedAddonRight || resolvedIconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: resolvedAddonRight || resolvedIconRight })
3954
+ (addonRight || iconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: addonRight || iconRight })
3457
3955
  ]
3458
3956
  }
3459
3957
  );
@@ -3518,7 +4016,7 @@ function SelectInput({
3518
4016
  triggerClassName,
3519
4017
  contentClassName,
3520
4018
  itemClassName,
3521
- Icon: Icon2,
4019
+ Icon,
3522
4020
  onValueChange,
3523
4021
  value: propValue,
3524
4022
  defaultOpen,
@@ -3529,24 +4027,34 @@ function SelectInput({
3529
4027
  }) {
3530
4028
  const descriptionText = description || helperText;
3531
4029
  const CLEAR_VALUE = "__CLEAR__";
3532
- const filteredItems = items.filter((item) => {
3533
- const val = item.value;
3534
- return val !== void 0 && val !== null;
3535
- });
3536
- const displayItems = allOption ? [allOption, ...filteredItems] : filteredItems;
3537
- const filteredGroups = groups.map((group) => ({
3538
- ...group,
3539
- items: group.items.filter((item) => {
3540
- const val = item.value;
3541
- return val !== void 0 && val !== null;
3542
- })
3543
- })).filter((group) => group.items.length > 0);
4030
+ const displayItems = useMemo(() => {
4031
+ const filtered = items.filter((item) => item.value !== void 0 && item.value !== null);
4032
+ return allOption ? [allOption, ...filtered] : filtered;
4033
+ }, [items, allOption]);
4034
+ const filteredGroups = useMemo(() => {
4035
+ return groups.map((group) => ({
4036
+ ...group,
4037
+ items: group.items.filter((item) => item.value !== void 0 && item.value !== null)
4038
+ })).filter((group) => group.items.length > 0);
4039
+ }, [groups]);
3544
4040
  const [localValue, setLocalValue] = useState(propValue?.toString() || "");
3545
4041
  useEffect(() => {
3546
4042
  if (propValue !== void 0) {
3547
4043
  setLocalValue(propValue.toString());
3548
4044
  }
3549
4045
  }, [propValue]);
4046
+ const labelMap = useMemo(() => {
4047
+ const map = /* @__PURE__ */ new Map();
4048
+ for (const item of displayItems) {
4049
+ map.set(item.value?.toString() ?? "", item.label);
4050
+ }
4051
+ for (const group of filteredGroups) {
4052
+ for (const item of group.items) {
4053
+ map.set(item.value?.toString() ?? "", item.label);
4054
+ }
4055
+ }
4056
+ return map;
4057
+ }, [displayItems, filteredGroups]);
3550
4058
  const renderSelect = (field, isDisabled, fieldState) => {
3551
4059
  const rawValue = field ? field.value?.toString() : localValue;
3552
4060
  const handleChange = (newValue) => {
@@ -3615,25 +4123,10 @@ function SelectInput({
3615
4123
  });
3616
4124
  };
3617
4125
  const selectValue = rawValue === "" ? CLEAR_VALUE : rawValue ? rawValue : void 0;
3618
- const findSelectedLabel = () => {
4126
+ const selectedLabel = (() => {
3619
4127
  if (!rawValue && rawValue !== "") return void 0;
3620
- for (const item of displayItems) {
3621
- const itemVal = item.value?.toString() ?? "";
3622
- if (itemVal === rawValue || itemVal === "" && rawValue === "") {
3623
- return item.label;
3624
- }
3625
- }
3626
- for (const group of filteredGroups) {
3627
- for (const item of group.items) {
3628
- const itemVal = item.value?.toString() ?? "";
3629
- if (itemVal === rawValue) {
3630
- return item.label;
3631
- }
3632
- }
3633
- }
3634
- return void 0;
3635
- };
3636
- const selectedLabel = findSelectedLabel();
4128
+ return labelMap.get(rawValue ?? "");
4129
+ })();
3637
4130
  return /* @__PURE__ */ jsxs(
3638
4131
  Select,
3639
4132
  {
@@ -3648,7 +4141,7 @@ function SelectInput({
3648
4141
  className: cn("w-full", triggerClassName),
3649
4142
  "aria-invalid": fieldState?.invalid || void 0,
3650
4143
  children: [
3651
- Icon2 && /* @__PURE__ */ jsx(Icon2, { className: "mr-2 h-4 w-4 text-primary" }),
4144
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "mr-2 h-4 w-4 text-primary" }),
3652
4145
  /* @__PURE__ */ jsx(SelectValue, { placeholder, children: selectedLabel || null })
3653
4146
  ]
3654
4147
  }
@@ -4072,7 +4565,7 @@ function DateInput({
4072
4565
  onValueChange,
4073
4566
  value: propValue,
4074
4567
  onChange: propOnChange,
4075
- Icon: Icon2 = CalendarIcon,
4568
+ Icon = CalendarIcon,
4076
4569
  allowClear = true
4077
4570
  }) {
4078
4571
  const descriptionText = description || helperText;
@@ -4121,7 +4614,7 @@ function DateInput({
4121
4614
  ),
4122
4615
  disabled: isDisabled,
4123
4616
  children: [
4124
- /* @__PURE__ */ jsx(Icon2, { className: "mr-2 h-4 w-4" }),
4617
+ /* @__PURE__ */ jsx(Icon, { className: "mr-2 h-4 w-4" }),
4125
4618
  displayText,
4126
4619
  allowClear && selected && !isDisabled && /* @__PURE__ */ jsx(
4127
4620
  X,
@@ -4871,110 +5364,108 @@ function generateSlug(text) {
4871
5364
  if (!text) return "";
4872
5365
  return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
4873
5366
  }
4874
- var SlugField = forwardRef(
4875
- ({
4876
- control,
4877
- name,
4878
- description,
4879
- helperText,
4880
- required,
4881
- label,
4882
- placeholder = "my-page-slug",
4883
- disabled,
4884
- sourceValue,
4885
- onGenerate,
4886
- className,
4887
- inputClassName,
4888
- labelClassName,
4889
- onValueChange,
4890
- value,
4891
- onChange,
4892
- error
4893
- }, ref) => {
4894
- const descriptionText = description || helperText;
4895
- const handleGenerate = (_currentValue, fieldOnChange) => {
4896
- const newSlug = onGenerate ? onGenerate(sourceValue || "") : generateSlug(sourceValue);
4897
- fieldOnChange?.(newSlug);
4898
- onValueChange?.(newSlug);
4899
- };
4900
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldState) => {
4901
- return /* @__PURE__ */ jsxs(InputGroup, { children: [
4902
- /* @__PURE__ */ jsx(
4903
- InputGroupInput,
4904
- {
4905
- ref,
4906
- id: name,
4907
- type: "text",
4908
- disabled: isDisabled,
4909
- placeholder,
4910
- value: fieldValue || "",
4911
- onChange: (e) => {
4912
- const newValue = e.target.value;
4913
- fieldOnChange?.(newValue);
4914
- onValueChange?.(newValue);
4915
- },
4916
- "aria-invalid": fieldState?.invalid,
4917
- className: inputClassName
4918
- }
4919
- ),
4920
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(
4921
- InputGroupButton,
4922
- {
4923
- type: "button",
4924
- size: "sm",
4925
- onClick: () => handleGenerate(fieldValue, fieldOnChange),
4926
- disabled: isDisabled || !sourceValue,
4927
- title: "Generate slug from source",
4928
- children: [
4929
- /* @__PURE__ */ jsx(Wand2, { className: "h-4 w-4" }),
4930
- "Generate"
4931
- ]
4932
- }
4933
- ) })
4934
- ] });
4935
- };
4936
- if (control && name) {
4937
- return /* @__PURE__ */ jsx(
4938
- Controller,
5367
+ function SlugField({
5368
+ control,
5369
+ name,
5370
+ description,
5371
+ helperText,
5372
+ required,
5373
+ label,
5374
+ placeholder = "my-page-slug",
5375
+ disabled,
5376
+ sourceValue,
5377
+ onGenerate,
5378
+ className,
5379
+ inputClassName,
5380
+ labelClassName,
5381
+ onValueChange,
5382
+ value,
5383
+ onChange,
5384
+ error,
5385
+ ref
5386
+ }) {
5387
+ const descriptionText = description || helperText;
5388
+ const handleGenerate = (_currentValue, fieldOnChange) => {
5389
+ const newSlug = onGenerate ? onGenerate(sourceValue || "") : generateSlug(sourceValue);
5390
+ fieldOnChange?.(newSlug);
5391
+ onValueChange?.(newSlug);
5392
+ };
5393
+ const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldState) => {
5394
+ return /* @__PURE__ */ jsxs(InputGroup, { children: [
5395
+ /* @__PURE__ */ jsx(
5396
+ InputGroupInput,
4939
5397
  {
4940
- name,
4941
- control,
4942
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(
4943
- Field,
4944
- {
4945
- className,
4946
- "data-disabled": disabled,
4947
- "data-invalid": fieldState.invalid,
4948
- children: [
4949
- label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4950
- label,
4951
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
4952
- ] }),
4953
- renderInput(field.value, field.onChange, disabled, fieldState),
4954
- descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
4955
- fieldState.invalid && fieldState.error && /* @__PURE__ */ jsx(FieldError, { errors: [fieldState.error] })
4956
- ]
4957
- }
4958
- )
5398
+ ref,
5399
+ id: name,
5400
+ type: "text",
5401
+ disabled: isDisabled,
5402
+ placeholder,
5403
+ value: fieldValue || "",
5404
+ onChange: (e) => {
5405
+ const newValue = e.target.value;
5406
+ fieldOnChange?.(newValue);
5407
+ onValueChange?.(newValue);
5408
+ },
5409
+ "aria-invalid": fieldState?.invalid,
5410
+ className: inputClassName
4959
5411
  }
4960
- );
4961
- }
4962
- const handleDirectChange = (newValue) => {
4963
- onChange?.({ target: { value: newValue } });
4964
- onValueChange?.(newValue);
4965
- };
4966
- return /* @__PURE__ */ jsxs(Field, { className, "data-disabled": disabled, children: [
4967
- label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4968
- label,
4969
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
4970
- ] }),
4971
- renderInput(value, handleDirectChange, disabled, { }),
4972
- descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
4973
- error && /* @__PURE__ */ jsx(FieldError, { errors: [error] })
5412
+ ),
5413
+ /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(
5414
+ InputGroupButton,
5415
+ {
5416
+ type: "button",
5417
+ size: "sm",
5418
+ onClick: () => handleGenerate(fieldValue, fieldOnChange),
5419
+ disabled: isDisabled || !sourceValue,
5420
+ title: "Generate slug from source",
5421
+ children: [
5422
+ /* @__PURE__ */ jsx(Wand2, { className: "h-4 w-4" }),
5423
+ "Generate"
5424
+ ]
5425
+ }
5426
+ ) })
4974
5427
  ] });
5428
+ };
5429
+ if (control && name) {
5430
+ return /* @__PURE__ */ jsx(
5431
+ Controller,
5432
+ {
5433
+ name,
5434
+ control,
5435
+ render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(
5436
+ Field,
5437
+ {
5438
+ className,
5439
+ "data-disabled": disabled,
5440
+ "data-invalid": fieldState.invalid,
5441
+ children: [
5442
+ label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
5443
+ label,
5444
+ required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
5445
+ ] }),
5446
+ renderInput(field.value, field.onChange, disabled, fieldState),
5447
+ descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
5448
+ fieldState.invalid && fieldState.error && /* @__PURE__ */ jsx(FieldError, { errors: [fieldState.error] })
5449
+ ]
5450
+ }
5451
+ )
5452
+ }
5453
+ );
4975
5454
  }
4976
- );
4977
- SlugField.displayName = "SlugField";
5455
+ const handleDirectChange = (newValue) => {
5456
+ onChange?.({ target: { value: newValue } });
5457
+ onValueChange?.(newValue);
5458
+ };
5459
+ return /* @__PURE__ */ jsxs(Field, { className, "data-disabled": disabled, children: [
5460
+ label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
5461
+ label,
5462
+ required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
5463
+ ] }),
5464
+ renderInput(value, handleDirectChange, disabled, { }),
5465
+ descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
5466
+ error && /* @__PURE__ */ jsx(FieldError, { errors: [error] })
5467
+ ] });
5468
+ }
4978
5469
  var flattenErrors = (errors, prefix = "") => {
4979
5470
  const flattened = [];
4980
5471
  Object.entries(errors).forEach(([key, value]) => {
@@ -5036,12 +5527,12 @@ function DateRangeFilter({
5036
5527
  alignRight = true,
5037
5528
  numberOfMonths = 1
5038
5529
  }) {
5039
- const [dateRange, setDateRange] = React5.useState(
5530
+ const [dateRange, setDateRange] = React3.useState(
5040
5531
  initialStartDate || initialEndDate ? { from: initialStartDate, to: initialEndDate } : void 0
5041
5532
  );
5042
- const [appliedRange, setAppliedRange] = React5.useState(dateRange);
5043
- const [open, setOpen] = React5.useState(false);
5044
- React5.useEffect(() => {
5533
+ const [appliedRange, setAppliedRange] = React3.useState(dateRange);
5534
+ const [open, setOpen] = React3.useState(false);
5535
+ React3.useEffect(() => {
5045
5536
  const newRange = initialStartDate || initialEndDate ? { from: initialStartDate, to: initialEndDate } : void 0;
5046
5537
  setDateRange(newRange);
5047
5538
  setAppliedRange(newRange);
@@ -5160,7 +5651,7 @@ function DateRangePopover({
5160
5651
  calendarClassName,
5161
5652
  allowClear,
5162
5653
  showBadge,
5163
- Icon: Icon2,
5654
+ Icon,
5164
5655
  formatDateRange,
5165
5656
  isDateDisabled,
5166
5657
  handleDateRangeSelect,
@@ -5187,7 +5678,7 @@ function DateRangePopover({
5187
5678
  buttonClassName
5188
5679
  ),
5189
5680
  children: [
5190
- /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4 shrink-0" }),
5681
+ /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0" }),
5191
5682
  hasValue ? /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate text-left", children: [
5192
5683
  formatDateRange(dateRange),
5193
5684
  showBadge && dateRange?.from && dateRange?.to && (() => {
@@ -5259,1442 +5750,178 @@ var defaultTransform = {
5259
5750
  } : { from: void 0, to: void 0 },
5260
5751
  output: (range) => ({
5261
5752
  from: range?.from ? range.from instanceof Date ? range.from.toISOString() : range.from : void 0,
5262
- to: range?.to ? range.to instanceof Date ? range.to.toISOString() : range.to : void 0
5263
- })
5264
- };
5265
- function DateRangeInput({
5266
- control,
5267
- name,
5268
- label,
5269
- description,
5270
- placeholder = "Select date range",
5271
- required,
5272
- disabled,
5273
- className,
5274
- labelClassName,
5275
- buttonClassName,
5276
- calendarClassName,
5277
- minDate,
5278
- maxDate,
5279
- disabledDates,
5280
- disabledDays,
5281
- onValueChange,
5282
- validateDateRange,
5283
- clearErrors,
5284
- descriptionComponent,
5285
- allowClear = true,
5286
- showBadge = false,
5287
- Icon: Icon2 = CalendarIcon,
5288
- transform = defaultTransform
5289
- }) {
5290
- const [localDateRange, setLocalDateRange] = useState({
5291
- from: void 0,
5292
- to: void 0
5293
- });
5294
- const formatDateRange = (range) => {
5295
- if (!range || !range.from && !range.to) return "";
5296
- const fromDate = range.from instanceof Date ? range.from : range.from ? new Date(range.from) : null;
5297
- const toDate2 = range.to instanceof Date ? range.to : range.to ? new Date(range.to) : null;
5298
- const fromFormatted = fromDate && isValid(fromDate) ? format(fromDate, "MMM d") : "";
5299
- const toFormatted = toDate2 && isValid(toDate2) ? format(toDate2, "MMM d") : "";
5300
- if (fromFormatted && toFormatted) {
5301
- return `${fromFormatted} - ${toFormatted}`;
5302
- } else if (fromFormatted) {
5303
- return `From ${fromFormatted}`;
5304
- } else if (toFormatted) {
5305
- return `Until ${toFormatted}`;
5306
- }
5307
- return "";
5308
- };
5309
- const isDateDisabled = (date) => {
5310
- if (!date || !isValid(date)) return true;
5311
- if (disabled) return true;
5312
- if (minDate && date < minDate) return true;
5313
- if (maxDate && date > maxDate) return true;
5314
- if (disabledDates?.some((d) => d.getTime() === date.getTime())) return true;
5315
- if (disabledDays?.includes(date.getDay())) return true;
5316
- return false;
5317
- };
5318
- const handleDateRangeSelect = (range, field) => {
5319
- if (disabled) return;
5320
- const safeRange = range || { from: void 0, to: void 0 };
5321
- if (validateDateRange && !validateDateRange(safeRange)) {
5322
- return;
5323
- }
5324
- if (field) {
5325
- const transformedValue = transform.output(safeRange);
5326
- field.onChange(transformedValue);
5327
- } else {
5328
- setLocalDateRange(safeRange);
5329
- }
5330
- onValueChange?.(safeRange);
5331
- if (clearErrors && name) {
5332
- clearErrors(name);
5333
- }
5334
- };
5335
- const handleClear = (field, e) => {
5336
- e.stopPropagation();
5337
- const emptyRange = { from: void 0, to: void 0 };
5338
- if (field) {
5339
- field.onChange(emptyRange);
5340
- } else {
5341
- setLocalDateRange(emptyRange);
5342
- }
5343
- onValueChange?.(emptyRange);
5344
- if (clearErrors && name) {
5345
- clearErrors(name);
5346
- }
5347
- };
5348
- if (control) {
5349
- return /* @__PURE__ */ jsx(
5350
- Controller,
5351
- {
5352
- control,
5353
- name,
5354
- render: ({ field, fieldState }) => {
5355
- const dateRange = transform.input(field.value);
5356
- return /* @__PURE__ */ jsxs(
5357
- Field,
5358
- {
5359
- className: cn("w-full", className),
5360
- "data-invalid": !!fieldState.error,
5361
- children: [
5362
- label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5363
- /* @__PURE__ */ jsxs(FieldLabel, { className: cn("grow", labelClassName), children: [
5364
- label,
5365
- required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5366
- ] }),
5367
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" }) })
5368
- ] }),
5369
- /* @__PURE__ */ jsx(
5370
- DateRangePopover,
5371
- {
5372
- dateRange,
5373
- placeholder,
5374
- disabled,
5375
- buttonClassName,
5376
- calendarClassName,
5377
- allowClear,
5378
- showBadge,
5379
- Icon: Icon2,
5380
- formatDateRange,
5381
- isDateDisabled,
5382
- handleDateRangeSelect: (range) => handleDateRangeSelect(range, field),
5383
- handleClear: (e) => handleClear(field, e),
5384
- minDate,
5385
- maxDate
5386
- }
5387
- ),
5388
- description && !descriptionComponent && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
5389
- descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent }),
5390
- /* @__PURE__ */ jsx(
5391
- FieldError,
5392
- {
5393
- errors: fieldState.error ? [fieldState.error] : void 0
5394
- }
5395
- )
5396
- ]
5397
- }
5398
- );
5399
- }
5400
- }
5401
- );
5402
- }
5403
- return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
5404
- label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5405
- /* @__PURE__ */ jsxs("div", { className: cn("text-sm font-medium grow", labelClassName), children: [
5406
- label,
5407
- required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5408
- ] }),
5409
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" }) })
5410
- ] }),
5411
- /* @__PURE__ */ jsx(
5412
- DateRangePopover,
5413
- {
5414
- dateRange: localDateRange,
5415
- placeholder,
5416
- disabled,
5417
- buttonClassName,
5418
- calendarClassName,
5419
- allowClear,
5420
- showBadge,
5421
- Icon: Icon2,
5422
- formatDateRange,
5423
- isDateDisabled,
5424
- handleDateRangeSelect: (range) => handleDateRangeSelect(range),
5425
- handleClear: (e) => handleClear(null, e),
5426
- minDate,
5427
- maxDate
5428
- }
5429
- ),
5430
- description && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mt-1", children: description }),
5431
- descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent })
5432
- ] });
5433
- }
5434
-
5435
- // src/components/search/index.ts
5436
- var search_exports = {};
5437
- __export(search_exports, {
5438
- Actions: () => SearchActions,
5439
- Container: () => SearchContainer,
5440
- FilterActions: () => SearchFilterActions,
5441
- Filters: () => SearchFilters,
5442
- Input: () => SearchInput,
5443
- Root: () => SearchRoot,
5444
- SearchProvider: () => SearchProvider,
5445
- TypeInput: () => SearchTypeInput,
5446
- useSearch: () => useSearch
5447
- });
5448
- var SearchContext = createContext(void 0);
5449
- function SearchProvider({ children, value }) {
5450
- return /* @__PURE__ */ jsx(SearchContext.Provider, { value, children });
5451
- }
5452
- function useSearch() {
5453
- const context = useContext(SearchContext);
5454
- if (!context) {
5455
- throw new Error("useSearch must be used within SearchProvider");
5456
- }
5457
- return context;
5458
- }
5459
- function SearchRoot({ children, hook, className }) {
5460
- return /* @__PURE__ */ jsx(SearchProvider, { value: hook, children: /* @__PURE__ */ jsx("div", { className: cn("w-full", className), children }) });
5461
- }
5462
- function SearchInput({
5463
- placeholder = "Search...",
5464
- className,
5465
- disabled,
5466
- showIcon = true,
5467
- showClearButton = false,
5468
- onKeyDown,
5469
- ...props
5470
- }) {
5471
- const { searchValue, setSearchValue, handleSearch } = useSearch();
5472
- const handleKeyDown = (event) => {
5473
- onKeyDown?.(event);
5474
- if (!event.defaultPrevented && event.key === "Enter" && !disabled) {
5475
- handleSearch?.();
5476
- }
5477
- };
5478
- return /* @__PURE__ */ jsxs(
5479
- InputGroup,
5480
- {
5481
- className: cn("h-10 flex-1 shadow-sm", className),
5482
- "data-disabled": disabled || void 0,
5483
- children: [
5484
- showIcon && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(Search, { className: "size-4" }) }),
5485
- /* @__PURE__ */ jsx(
5486
- InputGroupInput,
5487
- {
5488
- ...props,
5489
- type: "text",
5490
- placeholder,
5491
- value: searchValue || "",
5492
- onChange: (e) => setSearchValue?.(e.target.value),
5493
- onKeyDown: handleKeyDown,
5494
- disabled,
5495
- className: "text-base"
5496
- }
5497
- ),
5498
- showClearButton && searchValue && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
5499
- InputGroupButton,
5500
- {
5501
- variant: "ghost",
5502
- size: "icon-sm",
5503
- onClick: () => setSearchValue?.(""),
5504
- disabled,
5505
- children: /* @__PURE__ */ jsx(X, { className: "size-4" })
5506
- }
5507
- ) })
5508
- ]
5509
- }
5510
- );
5511
- }
5512
- function SearchTypeInput({
5513
- placeholder = "Search...",
5514
- className,
5515
- disabled,
5516
- showIcon = true,
5517
- showClearButton = false,
5518
- searchTypeOptions = [],
5519
- onKeyDown,
5520
- ...props
5521
- }) {
5522
- const { searchValue, setSearchValue, searchType, setSearchType, handleSearch } = useSearch();
5523
- const handleKeyDown = (event) => {
5524
- onKeyDown?.(event);
5525
- if (!event.defaultPrevented && event.key === "Enter" && !disabled) {
5526
- handleSearch?.();
5527
- }
5528
- };
5529
- const selectedOption = searchTypeOptions.find((opt) => opt.value === searchType);
5530
- return /* @__PURE__ */ jsxs(
5531
- InputGroup,
5532
- {
5533
- className: cn("h-10 flex-1 shadow-sm", className),
5534
- "data-disabled": disabled || void 0,
5535
- children: [
5536
- showIcon && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(Search, { className: "size-4" }) }),
5537
- searchTypeOptions.length > 0 && /* @__PURE__ */ jsxs(InputGroupAddon, { align: "inline-start", className: "pr-0", children: [
5538
- /* @__PURE__ */ jsxs(
5539
- Select,
5540
- {
5541
- value: searchType,
5542
- onValueChange: setSearchType,
5543
- disabled,
5544
- children: [
5545
- /* @__PURE__ */ jsx(SelectTrigger, { className: "h-7 w-auto border-0 bg-transparent px-2 text-sm font-medium shadow-none focus:ring-0", children: /* @__PURE__ */ jsx(SelectValue, { children: selectedOption?.label || searchTypeOptions[0]?.label }) }),
5546
- /* @__PURE__ */ jsx(SelectContent, { children: searchTypeOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
5547
- ]
5548
- }
5549
- ),
5550
- /* @__PURE__ */ jsx("div", { className: "h-6 w-px bg-border ml-1" })
5551
- ] }),
5552
- /* @__PURE__ */ jsx(
5553
- InputGroupInput,
5554
- {
5555
- ...props,
5556
- type: "text",
5557
- placeholder,
5558
- value: searchValue || "",
5559
- onChange: (e) => setSearchValue?.(e.target.value),
5560
- onKeyDown: handleKeyDown,
5561
- disabled,
5562
- className: "text-base"
5563
- }
5564
- ),
5565
- showClearButton && searchValue && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
5566
- InputGroupButton,
5567
- {
5568
- variant: "ghost",
5569
- size: "icon-sm",
5570
- onClick: () => setSearchValue?.(""),
5571
- disabled,
5572
- children: /* @__PURE__ */ jsx(X, { className: "size-4" })
5573
- }
5574
- ) })
5575
- ]
5576
- }
5577
- );
5578
- }
5579
- function SearchFilterActions({ onClose, disabled }) {
5580
- const { handleSearch, clearSearch, hasActiveFilters } = useSearch();
5581
- const handleApply = () => {
5582
- handleSearch?.();
5583
- onClose?.();
5584
- };
5585
- return /* @__PURE__ */ jsxs("div", { className: "flex gap-2 border-t bg-muted/30 p-4 pt-3 -mx-4 -mb-4", children: [
5586
- /* @__PURE__ */ jsx(
5587
- Button,
5588
- {
5589
- variant: "outline",
5590
- size: "sm",
5591
- onClick: clearSearch,
5592
- className: "flex-1",
5593
- disabled: disabled || !hasActiveFilters,
5594
- children: "Reset"
5595
- }
5596
- ),
5597
- /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: handleApply, className: "flex-1", disabled, children: [
5598
- /* @__PURE__ */ jsx(Search, { size: 16, className: "mr-2" }),
5599
- "Apply"
5600
- ] })
5601
- ] });
5602
- }
5603
- function SearchFilters({
5604
- children,
5605
- title = "Filters",
5606
- description = "Refine your search results",
5607
- disabled,
5608
- className
5609
- }) {
5610
- const { hasActiveFilters, filters = {} } = useSearch();
5611
- const isMobile = useIsMobile();
5612
- const [isOpen, setIsOpen] = useState(false);
5613
- const activeFilterCount = Object.values(filters).filter((value) => {
5614
- if (Array.isArray(value)) {
5615
- return value.filter(Boolean).length > 0;
5616
- }
5617
- if (typeof value === "string") {
5618
- return value.trim().length > 0 && value !== "all";
5619
- }
5620
- if (typeof value === "number") {
5621
- return value !== void 0 && value !== null && !Number.isNaN(value);
5622
- }
5623
- if (typeof value === "boolean") {
5624
- return value;
5625
- }
5626
- return Boolean(value);
5627
- }).length;
5628
- const FilterContent = () => /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
5629
- /* @__PURE__ */ jsx("div", { className: "space-y-4", children }),
5630
- /* @__PURE__ */ jsx(SearchFilterActions, { onClose: () => setIsOpen(false) })
5631
- ] });
5632
- const triggerButton = /* @__PURE__ */ jsxs(
5633
- Button,
5634
- {
5635
- variant: "outline",
5636
- size: "default",
5637
- className: cn(
5638
- "relative h-10 w-10 shrink-0 px-0 sm:w-auto sm:px-4",
5639
- hasActiveFilters && "bg-primary/10 border-primary hover:bg-primary/15"
5640
- ),
5641
- disabled,
5642
- "aria-label": "Open filters",
5643
- children: [
5644
- /* @__PURE__ */ jsx(Filter, { className: "size-4" }),
5645
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline ml-2", children: "Filters" }),
5646
- activeFilterCount > 0 && /* @__PURE__ */ jsx(
5647
- Badge,
5648
- {
5649
- variant: "secondary",
5650
- className: "absolute -right-1 -top-1 flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1 text-xs font-medium text-primary-foreground",
5651
- children: activeFilterCount
5652
- }
5653
- )
5654
- ]
5655
- }
5656
- );
5657
- if (isMobile) {
5658
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5659
- /* @__PURE__ */ jsxs(
5660
- Button,
5661
- {
5662
- variant: "outline",
5663
- size: "default",
5664
- className: cn(
5665
- "relative h-10 w-10 shrink-0 px-0",
5666
- hasActiveFilters && "bg-primary/10 border-primary hover:bg-primary/15"
5667
- ),
5668
- disabled,
5669
- "aria-label": "Open filters",
5670
- onClick: () => setIsOpen(true),
5671
- children: [
5672
- /* @__PURE__ */ jsx(Filter, { className: "size-4" }),
5673
- activeFilterCount > 0 && /* @__PURE__ */ jsx(
5674
- Badge,
5675
- {
5676
- variant: "secondary",
5677
- className: "absolute -right-1 -top-1 flex h-5 min-w-5 items-center justify-center rounded-full bg-primary px-1 text-xs font-medium text-primary-foreground",
5678
- children: activeFilterCount
5679
- }
5680
- )
5681
- ]
5682
- }
5683
- ),
5684
- /* @__PURE__ */ jsx(
5685
- SheetWrapper,
5686
- {
5687
- open: isOpen,
5688
- onOpenChange: setIsOpen,
5689
- title,
5690
- description,
5691
- side: "bottom",
5692
- size: "default",
5693
- children: /* @__PURE__ */ jsx(FilterContent, {})
5694
- }
5695
- )
5696
- ] });
5697
- }
5698
- return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
5699
- /* @__PURE__ */ jsx(PopoverTrigger, { render: triggerButton }),
5700
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-80 p-4 sm:w-96", align: "end", sideOffset: 8, children: /* @__PURE__ */ jsx(FilterContent, {}) })
5701
- ] });
5702
- }
5703
- function SearchActions({
5704
- showSearchButton = true,
5705
- showClearButton = true,
5706
- searchButtonText,
5707
- clearButtonText = "Clear",
5708
- disabled,
5709
- className
5710
- }) {
5711
- const { handleSearch, clearSearch, searchValue, hasActiveFilters, hasActiveSearch } = useSearch();
5712
- const isMobile = useIsMobile();
5713
- const canSearch = Boolean(searchValue?.trim() || hasActiveFilters);
5714
- const canClear = Boolean(searchValue?.trim() || hasActiveFilters || hasActiveSearch);
5715
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
5716
- showClearButton && canClear && (isMobile ? /* @__PURE__ */ jsx(
5717
- Button,
5718
- {
5719
- variant: "outline",
5720
- size: "icon",
5721
- onClick: clearSearch,
5722
- "aria-label": clearButtonText,
5723
- title: clearButtonText,
5724
- className: "shrink-0",
5725
- children: /* @__PURE__ */ jsx(RotateCcw, {})
5726
- }
5727
- ) : /* @__PURE__ */ jsx(
5728
- Button,
5729
- {
5730
- variant: "outline",
5731
- size: "default",
5732
- onClick: clearSearch,
5733
- className: "h-10 shrink-0",
5734
- children: clearButtonText
5735
- }
5736
- )),
5737
- showSearchButton && /* @__PURE__ */ jsxs(
5738
- Button,
5739
- {
5740
- size: "default",
5741
- onClick: handleSearch,
5742
- disabled: disabled || !canSearch,
5743
- className: "h-10 shrink-0 px-3 sm:px-4",
5744
- children: [
5745
- /* @__PURE__ */ jsx(
5746
- Search,
5747
- {
5748
- size: 16,
5749
- className: cn(searchButtonText ? "mr-2" : "sm:mr-2")
5750
- }
5751
- ),
5752
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: searchButtonText || "Search" })
5753
- ]
5754
- }
5755
- )
5756
- ] });
5757
- }
5758
- function SearchContainer({ children, className }) {
5759
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2 flex-1", className), children });
5760
- }
5761
- var FieldContext = createContext(null);
5762
- var Root = memo(function FieldRoot({
5763
- children,
5764
- className,
5765
- disabled = false,
5766
- invalid = false
5767
- }) {
5768
- const id = useId();
5769
- const value = useMemo(() => ({
5770
- id,
5771
- disabled,
5772
- invalid
5773
- }), [id, disabled, invalid]);
5774
- return /* @__PURE__ */ jsx(FieldContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: cn("w-full", className), children }) });
5775
- });
5776
- var Label = memo(function FieldLabel13({ children, className }) {
5777
- const ctx = useContext(FieldContext);
5778
- return /* @__PURE__ */ jsx(
5779
- "label",
5780
- {
5781
- htmlFor: ctx?.id,
5782
- className: cn(
5783
- "absolute left-3 top-0 -translate-y-1/2 bg-background px-2",
5784
- "text-xs font-medium text-muted-foreground z-10",
5785
- "group-focus-within:text-primary whitespace-nowrap",
5786
- ctx?.disabled && "opacity-60",
5787
- ctx?.invalid && "text-destructive",
5788
- className
5789
- ),
5790
- children
5791
- }
5792
- );
5793
- });
5794
- var Error2 = memo(function FieldError13({ children, className }) {
5795
- if (!children) return null;
5796
- return /* @__PURE__ */ jsx("p", { className: cn("text-xs text-destructive mt-1.5", className), children });
5797
- });
5798
- var Icon = memo(function FieldIcon({ children, className }) {
5799
- return /* @__PURE__ */ jsx("div", { className: cn(
5800
- "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none z-10",
5801
- "text-muted-foreground",
5802
- className
5803
- ), children });
5804
- });
5805
- var Field13 = {
5806
- Root,
5807
- Label,
5808
- Error: Error2,
5809
- Icon
5810
- };
5811
- var CompactInput = forwardRef(({
5812
- // Form integration
5813
- control,
5814
- name,
5815
- description,
5816
- required,
5817
- // Basic props
5818
- label,
5819
- placeholder,
5820
- disabled,
5821
- type = "text",
5822
- // InputGroup addons
5823
- AddonLeft,
5824
- AddonRight,
5825
- // Styling
5826
- className,
5827
- inputClassName,
5828
- // Events
5829
- onValueChange,
5830
- // Direct usage
5831
- value,
5832
- onChange,
5833
- error,
5834
- // Valid HTML input attributes
5835
- autoComplete,
5836
- autoFocus,
5837
- maxLength,
5838
- minLength,
5839
- max,
5840
- min,
5841
- pattern,
5842
- readOnly,
5843
- step,
5844
- inputMode,
5845
- enterKeyHint,
5846
- ...props
5847
- }, ref) => {
5848
- const hasInputGroup = AddonLeft || AddonRight;
5849
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldError) => {
5850
- const inputProps = {
5851
- ref,
5852
- id: name,
5853
- name,
5854
- type,
5855
- disabled: isDisabled,
5856
- placeholder,
5857
- value: fieldValue || "",
5858
- onChange: (e) => {
5859
- const newValue = e.target.value;
5860
- fieldOnChange?.(newValue);
5861
- onValueChange?.(newValue);
5862
- },
5863
- className: cn(
5864
- "h-11",
5865
- fieldError && "border-destructive focus-visible:ring-destructive/20",
5866
- inputClassName
5867
- ),
5868
- autoComplete,
5869
- autoFocus,
5870
- maxLength,
5871
- minLength,
5872
- max,
5873
- min,
5874
- pattern,
5875
- readOnly,
5876
- step,
5877
- inputMode,
5878
- enterKeyHint,
5879
- ...props
5880
- };
5881
- if (hasInputGroup) {
5882
- return /* @__PURE__ */ jsxs(InputGroup, { children: [
5883
- AddonLeft && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: AddonLeft }),
5884
- /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps }),
5885
- AddonRight && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: AddonRight })
5886
- ] });
5887
- }
5888
- return /* @__PURE__ */ jsx(Input, { ...inputProps });
5889
- };
5890
- if (control && name) {
5891
- return /* @__PURE__ */ jsx(
5892
- Controller,
5893
- {
5894
- name,
5895
- control,
5896
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
5897
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
5898
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
5899
- renderInput(field.value, field.onChange, disabled, fieldState?.error?.message)
5900
- ] }),
5901
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
5902
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
5903
- ] })
5904
- }
5905
- );
5906
- }
5907
- const handleDirectChange = (newValue) => {
5908
- onChange?.({ target: { value: newValue } });
5909
- onValueChange?.(newValue);
5910
- };
5911
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
5912
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
5913
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
5914
- renderInput(value, handleDirectChange, disabled, error)
5915
- ] }),
5916
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
5917
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
5918
- ] });
5919
- });
5920
- CompactInput.displayName = "CompactInput";
5921
- var CompactTextarea = forwardRef(({
5922
- // Form integration
5923
- control,
5924
- name,
5925
- description,
5926
- required,
5927
- // Basic props
5928
- label,
5929
- placeholder,
5930
- disabled,
5931
- rows = 3,
5932
- // InputGroup addons
5933
- AddonLeft,
5934
- AddonRight,
5935
- // Styling
5936
- className,
5937
- inputClassName,
5938
- // Events
5939
- onValueChange,
5940
- // Direct usage
5941
- value,
5942
- onChange,
5943
- error,
5944
- // Valid HTML textarea attributes
5945
- cols,
5946
- wrap,
5947
- autoComplete,
5948
- autoFocus,
5949
- maxLength,
5950
- minLength,
5951
- readOnly,
5952
- spellCheck,
5953
- ...props
5954
- }, ref) => {
5955
- const hasInputGroup = AddonLeft || AddonRight;
5956
- const renderTextarea = (fieldValue, fieldOnChange, isDisabled, fieldError) => {
5957
- const currentCharCount = fieldValue?.length || 0;
5958
- const textareaProps = {
5959
- ref,
5960
- id: name,
5961
- name,
5962
- disabled: isDisabled,
5963
- placeholder,
5964
- rows,
5965
- value: fieldValue || "",
5966
- onChange: (e) => {
5967
- const newValue = e.target.value;
5968
- fieldOnChange?.(newValue);
5969
- onValueChange?.(newValue);
5970
- },
5971
- className: cn(
5972
- "resize-none pt-3",
5973
- fieldError && "border-destructive focus-visible:ring-destructive/20",
5974
- inputClassName
5975
- ),
5976
- cols,
5977
- wrap,
5978
- autoComplete,
5979
- autoFocus,
5980
- maxLength,
5981
- minLength,
5982
- readOnly,
5983
- spellCheck,
5984
- ...props
5985
- };
5986
- if (hasInputGroup) {
5987
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5988
- /* @__PURE__ */ jsxs(InputGroup, { children: [
5989
- AddonLeft && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-start", children: AddonLeft }),
5990
- /* @__PURE__ */ jsx(InputGroupTextarea, { ...textareaProps }),
5991
- AddonRight && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-end", children: AddonRight })
5992
- ] }),
5993
- maxLength && currentCharCount > 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1.5 text-right", children: [
5994
- currentCharCount,
5995
- "/",
5996
- maxLength
5997
- ] })
5998
- ] });
5999
- }
6000
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6001
- /* @__PURE__ */ jsx(Textarea, { ...textareaProps }),
6002
- maxLength && currentCharCount > 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1.5 text-right", children: [
6003
- currentCharCount,
6004
- "/",
6005
- maxLength
6006
- ] })
6007
- ] });
6008
- };
6009
- if (control && name) {
6010
- return /* @__PURE__ */ jsx(
6011
- Controller,
6012
- {
6013
- name,
6014
- control,
6015
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
6016
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6017
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6018
- renderTextarea(field.value, field.onChange, disabled, fieldState?.error?.message)
6019
- ] }),
6020
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6021
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6022
- ] })
6023
- }
6024
- );
6025
- }
6026
- const handleDirectChange = (newValue) => {
6027
- onChange?.({ target: { value: newValue } });
6028
- onValueChange?.(newValue);
6029
- };
6030
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
6031
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6032
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6033
- renderTextarea(value, handleDirectChange, disabled, error)
6034
- ] }),
6035
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
6036
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6037
- ] });
6038
- });
6039
- CompactTextarea.displayName = "CompactTextarea";
6040
- var CompactSelect = forwardRef(({
6041
- // Form integration
6042
- control,
6043
- name,
6044
- description,
6045
- required,
6046
- // Basic props
6047
- label,
6048
- placeholder = "Select option",
6049
- disabled,
6050
- items = [],
6051
- // Styling
6052
- className,
6053
- // Events
6054
- onValueChange,
6055
- // Direct usage
6056
- value,
6057
- error,
6058
- ...props
6059
- }, ref) => {
6060
- if (control && name) {
6061
- return /* @__PURE__ */ jsx(
6062
- Controller,
6063
- {
6064
- name,
6065
- control,
6066
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { disabled, invalid: !!fieldState?.error, children: [
6067
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6068
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6069
- /* @__PURE__ */ jsxs(
6070
- Select,
6071
- {
6072
- value: field.value,
6073
- onValueChange: (val) => {
6074
- field.onChange(val);
6075
- onValueChange?.(val);
6076
- },
6077
- disabled,
6078
- ...props,
6079
- children: [
6080
- /* @__PURE__ */ jsx(
6081
- SelectTrigger,
6082
- {
6083
- ref,
6084
- id: name,
6085
- className: cn(
6086
- "h-11",
6087
- fieldState?.error && "border-destructive focus:ring-destructive/20",
6088
- className
6089
- ),
6090
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
6091
- }
6092
- ),
6093
- /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
6094
- ]
6095
- }
6096
- )
6097
- ] }),
6098
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6099
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6100
- ] })
6101
- }
6102
- );
6103
- }
6104
- return /* @__PURE__ */ jsxs(Field13.Root, { disabled, invalid: !!error, children: [
6105
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6106
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6107
- /* @__PURE__ */ jsxs(
6108
- Select,
6109
- {
6110
- value,
6111
- onValueChange,
6112
- disabled,
6113
- ...props,
6114
- children: [
6115
- /* @__PURE__ */ jsx(
6116
- SelectTrigger,
6117
- {
6118
- ref,
6119
- className: cn(
6120
- "h-11",
6121
- error && "border-destructive focus:ring-destructive/20",
6122
- className
6123
- ),
6124
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
6125
- }
6126
- ),
6127
- /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
6128
- ]
6129
- }
6130
- )
6131
- ] }),
6132
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6133
- ] });
6134
- });
6135
- CompactSelect.displayName = "CompactSelect";
6136
- var CompactNumberInput = forwardRef(({
6137
- // Form integration
6138
- control,
6139
- name,
6140
- description,
6141
- required,
6142
- // Basic props
6143
- label,
6144
- placeholder,
6145
- disabled,
6146
- // Number configuration
6147
- min = 0,
6148
- max,
6149
- step = 1,
6150
- // Display options
6151
- prefix,
6152
- suffix,
6153
- showButtons = false,
6154
- buttonVariant = "ghost",
6155
- // Styling
6156
- className,
6157
- inputClassName,
6158
- labelClassName,
6159
- containerClassName,
6160
- // Events
6161
- onValueChange,
6162
- // Direct usage
6163
- value,
6164
- defaultValue,
6165
- onChange,
6166
- error,
6167
- ...props
6168
- }, ref) => {
6169
- if (control && name) {
6170
- return /* @__PURE__ */ jsx(
6171
- Controller,
6172
- {
6173
- name,
6174
- control,
6175
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(
6176
- CompactNumberInputInternal,
6177
- {
6178
- ref,
6179
- label,
6180
- placeholder,
6181
- disabled,
6182
- min,
6183
- max,
6184
- step,
6185
- prefix,
6186
- suffix,
6187
- showButtons,
6188
- buttonVariant,
6189
- className,
6190
- inputClassName,
6191
- labelClassName,
6192
- containerClassName,
6193
- error: fieldState?.error?.message,
6194
- value: field.value ?? "",
6195
- onChange: (val) => {
6196
- field.onChange(val);
6197
- onValueChange?.(val);
6198
- },
6199
- ...props
6200
- }
6201
- )
6202
- }
6203
- );
6204
- }
6205
- return /* @__PURE__ */ jsx(
6206
- CompactNumberInputInternal,
6207
- {
6208
- ref,
6209
- label,
6210
- placeholder,
6211
- disabled,
6212
- min,
6213
- max,
6214
- step,
6215
- prefix,
6216
- suffix,
6217
- showButtons,
6218
- buttonVariant,
6219
- className,
6220
- inputClassName,
6221
- labelClassName,
6222
- containerClassName,
6223
- error,
6224
- value: value ?? "",
6225
- defaultValue,
6226
- onChange,
6227
- onValueChange,
6228
- ...props
6229
- }
6230
- );
6231
- });
6232
- var CompactNumberInputInternal = forwardRef(({
6233
- label,
6234
- placeholder,
6235
- min = 0,
6236
- max,
6237
- step = 1,
6238
- prefix,
6239
- suffix,
6240
- showButtons,
6241
- buttonVariant,
6242
- error,
6243
- className,
6244
- inputClassName,
6245
- labelClassName,
6246
- containerClassName,
6247
- disabled,
6248
- value,
6249
- defaultValue,
6250
- onChange,
6251
- onValueChange,
6252
- ...props
6253
- }, ref) => {
6254
- const handleIncrement = () => {
6255
- const currentValue = Number(value) || 0;
6256
- const newValue = currentValue + step;
6257
- if (max === void 0 || newValue <= max) {
6258
- const finalValue = Number(newValue.toFixed(10));
6259
- onChange?.(finalValue);
6260
- onValueChange?.(finalValue);
6261
- }
6262
- };
6263
- const handleDecrement = () => {
6264
- const currentValue = Number(value) || 0;
6265
- const newValue = currentValue - step;
6266
- if (newValue >= min) {
6267
- const finalValue = Number(newValue.toFixed(10));
6268
- onChange?.(finalValue);
6269
- onValueChange?.(finalValue);
6270
- }
6271
- };
6272
- const handleInputChange = (e) => {
6273
- const val = e.target.value;
6274
- if (val === "") {
6275
- onChange?.("");
6276
- onValueChange?.("");
6277
- return;
6278
- }
6279
- const numVal = Number(val);
6280
- if (!isNaN(numVal)) {
6281
- if (min !== void 0 && numVal < min || max !== void 0 && numVal > max) {
6282
- return;
6283
- }
6284
- onChange?.(numVal);
6285
- onValueChange?.(numVal);
6286
- }
6287
- };
6288
- if (showButtons) {
6289
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6290
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6291
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6292
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(
6293
- InputGroupButton,
6294
- {
6295
- type: "button",
6296
- variant: buttonVariant,
6297
- size: "icon-sm",
6298
- onClick: handleDecrement,
6299
- disabled: disabled || Number(value) <= min,
6300
- children: /* @__PURE__ */ jsx(Minus, { className: "h-4 w-4" })
6301
- }
6302
- ) }),
6303
- /* @__PURE__ */ jsx(
6304
- InputGroupInput,
6305
- {
6306
- ref,
6307
- type: "number",
6308
- value,
6309
- defaultValue,
6310
- onChange: handleInputChange,
6311
- min,
6312
- max,
6313
- step,
6314
- disabled,
6315
- placeholder,
6316
- className: cn("text-center", inputClassName, className),
6317
- ...props
6318
- }
6319
- ),
6320
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
6321
- InputGroupButton,
6322
- {
6323
- type: "button",
6324
- variant: buttonVariant,
6325
- size: "icon-sm",
6326
- onClick: handleIncrement,
6327
- disabled: disabled || max !== void 0 && Number(value) >= max,
6328
- children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
6329
- }
6330
- ) })
6331
- ] }),
6332
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6333
- ] });
6334
- }
6335
- if (prefix || suffix) {
6336
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6337
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6338
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6339
- prefix && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: typeof prefix === "string" ? /* @__PURE__ */ jsx("span", { className: "text-xs", children: prefix }) : prefix }),
6340
- /* @__PURE__ */ jsx(
6341
- InputGroupInput,
6342
- {
6343
- ref,
6344
- type: "number",
6345
- value,
6346
- defaultValue,
6347
- onChange: handleInputChange,
6348
- min,
6349
- max,
6350
- step,
6351
- disabled,
6352
- placeholder,
6353
- className: cn(inputClassName, className),
6354
- ...props
6355
- }
6356
- ),
6357
- suffix && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: typeof suffix === "string" ? /* @__PURE__ */ jsx("span", { className: "text-xs", children: suffix }) : suffix })
6358
- ] }),
6359
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6360
- ] });
6361
- }
6362
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6363
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6364
- /* @__PURE__ */ jsx(
6365
- Input,
6366
- {
6367
- ref,
6368
- type: "number",
6369
- value,
6370
- defaultValue,
6371
- onChange: handleInputChange,
6372
- min,
6373
- max,
6374
- step,
6375
- disabled,
6376
- placeholder,
6377
- className: cn(
6378
- "h-11 transition-all duration-200",
6379
- error && "border-destructive focus-visible:ring-destructive/20",
6380
- inputClassName,
6381
- className
6382
- ),
6383
- ...props
6384
- }
6385
- ),
6386
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6387
- ] });
6388
- });
6389
- CompactNumberInput.displayName = "CompactNumberInput";
6390
- CompactNumberInputInternal.displayName = "CompactNumberInputInternal";
6391
- var CompactTagChoice = forwardRef(({
6392
- // Form integration
6393
- control,
6394
- name,
6395
- // Display
6396
- label,
6397
- description,
6398
- placeholder = "Select options...",
6399
- required,
6400
- disabled,
6401
- // Data
6402
- choices = [],
6403
- maxSelections,
6404
- // Styling
6405
- className,
6406
- containerClassName,
6407
- labelClassName,
6408
- inputClassName,
6409
- // Direct usage
6410
- value: propValue = [],
6411
- onChange: propOnChange,
6412
- onValueChange,
6413
- error
6414
- }, ref) => {
6415
- if (control && name) {
6416
- return /* @__PURE__ */ jsx(
6417
- Controller,
6418
- {
6419
- name,
6420
- control,
6421
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(
6422
- CompactTagChoiceInternal,
6423
- {
6424
- ref,
6425
- label,
6426
- placeholder,
6427
- disabled,
6428
- error: fieldState?.error?.message,
6429
- value: field.value || [],
6430
- onChange: (vals) => {
6431
- field.onChange(vals);
6432
- onValueChange?.(vals);
6433
- },
6434
- choices,
6435
- maxSelections,
6436
- containerClassName: cn(className, containerClassName),
6437
- labelClassName,
6438
- inputClassName
6439
- }
6440
- )
6441
- }
6442
- );
6443
- }
6444
- return /* @__PURE__ */ jsx(
6445
- CompactTagChoiceInternal,
6446
- {
6447
- ref,
6448
- label,
6449
- placeholder,
6450
- disabled,
6451
- value: propValue,
6452
- onChange: (vals) => {
6453
- propOnChange?.(vals);
6454
- onValueChange?.(vals);
6455
- },
6456
- choices,
6457
- maxSelections,
6458
- containerClassName,
6459
- labelClassName,
6460
- inputClassName,
6461
- className,
6462
- error
6463
- }
6464
- );
6465
- });
6466
- var CompactTagChoiceInternal = forwardRef(({
6467
- label,
6468
- placeholder,
6469
- disabled,
6470
- value = [],
6471
- onChange,
6472
- choices = [],
6473
- maxSelections,
6474
- error,
6475
- className,
6476
- containerClassName,
6477
- labelClassName,
6478
- inputClassName
6479
- }, ref) => {
6480
- const [open, setOpen] = useState(false);
6481
- const triggerRef = useRef(null);
6482
- const availableChoices = choices.filter((c) => !value.includes(c.value));
6483
- const addChoice = (choiceValue) => {
6484
- if (value.includes(choiceValue)) return;
6485
- if (maxSelections && value.length >= maxSelections) return;
6486
- const updated = [...value, choiceValue];
6487
- onChange?.(updated);
6488
- };
6489
- const removeChoice = (choiceValue) => {
6490
- const updated = value.filter((v) => v !== choiceValue);
6491
- onChange?.(updated);
6492
- };
6493
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6494
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6495
- /* @__PURE__ */ jsxs(
6496
- "div",
6497
- {
6498
- className: cn(
6499
- "min-h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
6500
- "ring-offset-background focus-within:ring-1 focus-within:ring-primary/20",
6501
- "hover:border-primary/50 transition-all duration-200",
6502
- error && "border-destructive focus-within:ring-destructive/20",
6503
- disabled && "opacity-50 cursor-not-allowed",
6504
- inputClassName
6505
- ),
6506
- ref,
6507
- children: [
6508
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 mb-2", children: value.map((val) => {
6509
- const choice = choices.find((c) => c.value === val);
6510
- return /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "flex items-center gap-1 px-2 py-1", children: [
6511
- /* @__PURE__ */ jsx("span", { children: choice?.label ?? val }),
6512
- !disabled && /* @__PURE__ */ jsx(
6513
- Button,
6514
- {
6515
- type: "button",
6516
- variant: "ghost",
6517
- size: "sm",
6518
- className: "h-auto p-0 text-muted-foreground hover:text-foreground",
6519
- onClick: (e) => {
6520
- e.preventDefault();
6521
- e.stopPropagation();
6522
- removeChoice(val);
6523
- },
6524
- children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
6525
- }
6526
- )
6527
- ] }, val);
6528
- }) }),
6529
- !disabled && availableChoices.length > 0 && (!maxSelections || value.length < maxSelections) && /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
6530
- /* @__PURE__ */ jsx(
6531
- PopoverTrigger,
6532
- {
6533
- render: /* @__PURE__ */ jsxs(
6534
- Button,
6535
- {
6536
- ref: triggerRef,
6537
- type: "button",
6538
- variant: "ghost",
6539
- className: cn(
6540
- "inline-flex items-center justify-center h-auto p-1 rounded-md text-sm font-medium transition-colors",
6541
- "text-muted-foreground hover:text-foreground hover:bg-accent",
6542
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
6543
- ),
6544
- onClick: (e) => {
6545
- e.preventDefault();
6546
- e.stopPropagation();
6547
- setOpen(true);
6548
- },
6549
- children: [
6550
- /* @__PURE__ */ jsx(Plus, { className: "h-3 w-3 mr-1" }),
6551
- value.length === 0 ? placeholder : "Add more..."
6552
- ]
6553
- }
6554
- )
6555
- }
6556
- ),
6557
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[220px] p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "p-1", children: [
6558
- availableChoices.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-2 py-3 text-sm text-muted-foreground text-center", children: "No options available" }) : /* @__PURE__ */ jsx("div", { className: "space-y-1", children: availableChoices.map((choice) => /* @__PURE__ */ jsxs(
6559
- "div",
6560
- {
6561
- onClick: (e) => {
6562
- e.preventDefault();
6563
- e.stopPropagation();
6564
- addChoice(choice.value);
6565
- },
6566
- className: "flex items-center justify-between px-2 py-2 text-sm rounded-sm hover:bg-accent hover:text-accent-foreground cursor-pointer",
6567
- children: [
6568
- /* @__PURE__ */ jsx("span", { children: choice.label }),
6569
- value.includes(choice.value) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" })
6570
- ]
6571
- },
6572
- choice.value
6573
- )) }),
6574
- /* @__PURE__ */ jsx("div", { className: "border-t px-2 py-2 text-xs text-muted-foreground", children: "Click to select \u2022 Click outside to close" })
6575
- ] }) })
6576
- ] }),
6577
- maxSelections && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1", children: [
6578
- value.length,
6579
- "/",
6580
- maxSelections,
6581
- " selected"
6582
- ] })
6583
- ]
6584
- }
6585
- ),
6586
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6587
- ] });
6588
- });
6589
- CompactTagChoice.displayName = "CompactTagChoice";
6590
- CompactTagChoiceInternal.displayName = "CompactTagChoiceInternal";
6591
- function generateSlug2(text) {
6592
- if (!text) return "";
6593
- return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
6594
- }
6595
- var CompactSlugField = forwardRef(({
6596
- // Form integration
5753
+ to: range?.to ? range.to instanceof Date ? range.to.toISOString() : range.to : void 0
5754
+ })
5755
+ };
5756
+ function DateRangeInput({
6597
5757
  control,
6598
5758
  name,
5759
+ label,
6599
5760
  description,
5761
+ placeholder = "Select date range",
6600
5762
  required,
6601
- // Basic props
6602
- label,
6603
- placeholder = "my-page-slug",
6604
5763
  disabled,
6605
- // Icon support
6606
- icon,
6607
- // Slug generation
6608
- sourceValue,
6609
- onGenerate,
6610
- // Styling
6611
5764
  className,
6612
- inputClassName,
6613
- // Events
5765
+ labelClassName,
5766
+ buttonClassName,
5767
+ calendarClassName,
5768
+ minDate,
5769
+ maxDate,
5770
+ disabledDates,
5771
+ disabledDays,
6614
5772
  onValueChange,
6615
- // Direct usage
6616
- value,
6617
- onChange,
6618
- error,
6619
- ...props
6620
- }, ref) => {
6621
- const handleGenerate = (currentValue, fieldOnChange) => {
6622
- const newSlug = onGenerate ? onGenerate(sourceValue || "") : generateSlug2(sourceValue || "");
6623
- fieldOnChange(newSlug);
6624
- onValueChange?.(newSlug);
5773
+ validateDateRange,
5774
+ clearErrors,
5775
+ descriptionComponent,
5776
+ allowClear = true,
5777
+ showBadge = false,
5778
+ Icon = CalendarIcon,
5779
+ transform = defaultTransform
5780
+ }) {
5781
+ const [localDateRange, setLocalDateRange] = useState({
5782
+ from: void 0,
5783
+ to: void 0
5784
+ });
5785
+ const formatDateRange = (range) => {
5786
+ if (!range || !range.from && !range.to) return "";
5787
+ const fromDate = range.from instanceof Date ? range.from : range.from ? new Date(range.from) : null;
5788
+ const toDate2 = range.to instanceof Date ? range.to : range.to ? new Date(range.to) : null;
5789
+ const fromFormatted = fromDate && isValid(fromDate) ? format(fromDate, "MMM d") : "";
5790
+ const toFormatted = toDate2 && isValid(toDate2) ? format(toDate2, "MMM d") : "";
5791
+ if (fromFormatted && toFormatted) {
5792
+ return `${fromFormatted} - ${toFormatted}`;
5793
+ } else if (fromFormatted) {
5794
+ return `From ${fromFormatted}`;
5795
+ } else if (toFormatted) {
5796
+ return `Until ${toFormatted}`;
5797
+ }
5798
+ return "";
6625
5799
  };
6626
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldState) => {
6627
- const inputProps = {
6628
- ref,
6629
- id: name,
6630
- type: "text",
6631
- disabled: isDisabled,
6632
- placeholder,
6633
- value: fieldValue || "",
6634
- onChange: (e) => {
6635
- const newValue = e.target.value;
6636
- fieldOnChange(newValue);
6637
- onValueChange?.(newValue);
6638
- },
6639
- className: cn(
6640
- "h-11",
6641
- fieldState?.error && "border-destructive focus-visible:ring-destructive/20",
6642
- inputClassName
6643
- ),
6644
- ...props
6645
- };
6646
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6647
- icon && /* @__PURE__ */ jsx(Field13.Icon, { children: icon }),
6648
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6649
- /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps, className: cn(inputProps.className, icon && "pl-9") }),
6650
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(
6651
- InputGroupButton,
6652
- {
6653
- type: "button",
6654
- size: "sm",
6655
- onClick: () => handleGenerate(fieldValue, fieldOnChange),
6656
- disabled: isDisabled || !sourceValue,
6657
- title: "Generate slug from name",
6658
- children: [
6659
- /* @__PURE__ */ jsx(Wand2, { className: "h-4 w-4" }),
6660
- "Generate"
6661
- ]
6662
- }
6663
- ) })
6664
- ] })
6665
- ] });
5800
+ const isDateDisabled = (date) => {
5801
+ if (!date || !isValid(date)) return true;
5802
+ if (disabled) return true;
5803
+ if (minDate && date < minDate) return true;
5804
+ if (maxDate && date > maxDate) return true;
5805
+ if (disabledDates?.some((d) => d.getTime() === date.getTime())) return true;
5806
+ if (disabledDays?.includes(date.getDay())) return true;
5807
+ return false;
6666
5808
  };
6667
- if (control && name) {
5809
+ const handleDateRangeSelect = (range, field) => {
5810
+ if (disabled) return;
5811
+ const safeRange = range || { from: void 0, to: void 0 };
5812
+ if (validateDateRange && !validateDateRange(safeRange)) {
5813
+ return;
5814
+ }
5815
+ if (field) {
5816
+ const transformedValue = transform.output(safeRange);
5817
+ field.onChange(transformedValue);
5818
+ } else {
5819
+ setLocalDateRange(safeRange);
5820
+ }
5821
+ onValueChange?.(safeRange);
5822
+ if (clearErrors && name) {
5823
+ clearErrors(name);
5824
+ }
5825
+ };
5826
+ const handleClear = (field, e) => {
5827
+ e.stopPropagation();
5828
+ const emptyRange = { from: void 0, to: void 0 };
5829
+ if (field) {
5830
+ field.onChange(emptyRange);
5831
+ } else {
5832
+ setLocalDateRange(emptyRange);
5833
+ }
5834
+ onValueChange?.(emptyRange);
5835
+ if (clearErrors && name) {
5836
+ clearErrors(name);
5837
+ }
5838
+ };
5839
+ if (control) {
6668
5840
  return /* @__PURE__ */ jsx(
6669
5841
  Controller,
6670
5842
  {
6671
- name,
6672
5843
  control,
6673
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
6674
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6675
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6676
- renderInput(field.value, field.onChange, disabled, fieldState)
6677
- ] }),
6678
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6679
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6680
- ] })
5844
+ name,
5845
+ render: ({ field, fieldState }) => {
5846
+ const dateRange = transform.input(field.value);
5847
+ return /* @__PURE__ */ jsxs(
5848
+ Field,
5849
+ {
5850
+ className: cn("w-full", className),
5851
+ "data-invalid": !!fieldState.error,
5852
+ children: [
5853
+ label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5854
+ /* @__PURE__ */ jsxs(FieldLabel, { className: cn("grow", labelClassName), children: [
5855
+ label,
5856
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5857
+ ] }),
5858
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }) })
5859
+ ] }),
5860
+ /* @__PURE__ */ jsx(
5861
+ DateRangePopover,
5862
+ {
5863
+ dateRange,
5864
+ placeholder,
5865
+ disabled,
5866
+ buttonClassName,
5867
+ calendarClassName,
5868
+ allowClear,
5869
+ showBadge,
5870
+ Icon,
5871
+ formatDateRange,
5872
+ isDateDisabled,
5873
+ handleDateRangeSelect: (range) => handleDateRangeSelect(range, field),
5874
+ handleClear: (e) => handleClear(field, e),
5875
+ minDate,
5876
+ maxDate
5877
+ }
5878
+ ),
5879
+ description && !descriptionComponent && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
5880
+ descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent }),
5881
+ /* @__PURE__ */ jsx(
5882
+ FieldError,
5883
+ {
5884
+ errors: fieldState.error ? [fieldState.error] : void 0
5885
+ }
5886
+ )
5887
+ ]
5888
+ }
5889
+ );
5890
+ }
6681
5891
  }
6682
5892
  );
6683
5893
  }
6684
- const handleDirectChange = (newValue) => {
6685
- onChange?.({ target: { value: newValue } });
6686
- onValueChange?.(newValue);
6687
- };
6688
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
6689
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6690
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6691
- renderInput(value, handleDirectChange, disabled, { error: error ? { message: error } : void 0 })
5894
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
5895
+ label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5896
+ /* @__PURE__ */ jsxs("div", { className: cn("text-sm font-medium grow", labelClassName), children: [
5897
+ label,
5898
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5899
+ ] }),
5900
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }) })
6692
5901
  ] }),
6693
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
6694
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
5902
+ /* @__PURE__ */ jsx(
5903
+ DateRangePopover,
5904
+ {
5905
+ dateRange: localDateRange,
5906
+ placeholder,
5907
+ disabled,
5908
+ buttonClassName,
5909
+ calendarClassName,
5910
+ allowClear,
5911
+ showBadge,
5912
+ Icon,
5913
+ formatDateRange,
5914
+ isDateDisabled,
5915
+ handleDateRangeSelect: (range) => handleDateRangeSelect(range),
5916
+ handleClear: (e) => handleClear(null, e),
5917
+ minDate,
5918
+ maxDate
5919
+ }
5920
+ ),
5921
+ description && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mt-1", children: description }),
5922
+ descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent })
6695
5923
  ] });
6696
- });
6697
- CompactSlugField.displayName = "CompactSlugField";
5924
+ }
6698
5925
  var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
6699
5926
  function EventCalendar({
6700
5927
  events = [],
@@ -6959,57 +6186,275 @@ function CalendarWithDetail({
6959
6186
  }
6960
6187
  );
6961
6188
  }
6962
- var backgrounds = {
6963
- default: "bg-background",
6964
- muted: "bg-muted",
6965
- primary: "bg-primary text-primary-foreground",
6966
- transparent: "bg-transparent"
6189
+ var ANIMATION_CLASSES = {
6190
+ fadeIn: "animate-fade-in",
6191
+ fadeInUp: "animate-fade-in-up",
6192
+ scaleIn: "animate-scale-in",
6193
+ slideInLeft: "animate-slide-in-left",
6194
+ slideInRight: "animate-slide-in-right",
6195
+ slideInUp: "animate-slide-in-up",
6196
+ slideInDown: "animate-slide-in-down"
6967
6197
  };
6968
- var paddings = {
6969
- none: "",
6970
- sm: "py-8 md:py-12",
6971
- md: "py-12 md:py-16",
6972
- lg: "py-16 md:py-24",
6973
- xl: "py-24 md:py-32"
6198
+ var SLIDE_MAP = {
6199
+ left: "slideInLeft",
6200
+ right: "slideInRight",
6201
+ up: "slideInUp",
6202
+ down: "slideInDown"
6974
6203
  };
6975
- function Section({
6976
- id,
6204
+ function useInView(ref, options = {}) {
6205
+ const { margin = "0px", once = true, enabled = true } = options;
6206
+ const [inView, setInView] = useState(false);
6207
+ useEffect(() => {
6208
+ if (!enabled) return;
6209
+ const el = ref.current;
6210
+ if (!el) return;
6211
+ const observer = new IntersectionObserver(
6212
+ ([entry]) => {
6213
+ if (entry.isIntersecting) {
6214
+ setInView(true);
6215
+ if (once) observer.unobserve(el);
6216
+ } else if (!once) {
6217
+ setInView(false);
6218
+ }
6219
+ },
6220
+ { rootMargin: margin }
6221
+ );
6222
+ observer.observe(el);
6223
+ return () => observer.disconnect();
6224
+ }, [enabled, margin, once]);
6225
+ return inView;
6226
+ }
6227
+ function useAnimationState(opts) {
6228
+ const ref = useRef(null);
6229
+ const shouldAnimate = !opts.disabled;
6230
+ const isInView = useInView(ref, {
6231
+ margin: opts.inViewMargin,
6232
+ once: opts.once,
6233
+ enabled: !!opts.inView && shouldAnimate
6234
+ });
6235
+ const active = shouldAnimate && (!opts.inView || isInView);
6236
+ return { ref, shouldAnimate, active };
6237
+ }
6238
+ function animTimingStyle(delay, duration) {
6239
+ if (delay === 0 && duration === 600) return void 0;
6240
+ return {
6241
+ ...duration !== 600 ? { animationDuration: `${duration}ms` } : {},
6242
+ ...delay > 0 ? { animationDelay: `${delay}ms` } : {}
6243
+ };
6244
+ }
6245
+ function AnimateBase({
6246
+ animation,
6977
6247
  children,
6248
+ delay = 0,
6249
+ duration = 600,
6250
+ inView = false,
6251
+ inViewMargin,
6252
+ once = true,
6253
+ disabled = false,
6978
6254
  className,
6979
- background = "default",
6980
- padding = "sm"
6255
+ as = "div"
6981
6256
  }) {
6982
- return /* @__PURE__ */ jsx(
6983
- "section",
6257
+ const { ref, shouldAnimate, active } = useAnimationState({
6258
+ inView,
6259
+ inViewMargin,
6260
+ once,
6261
+ disabled
6262
+ });
6263
+ return createElement(
6264
+ as,
6984
6265
  {
6985
- id,
6986
- className: cn(backgrounds[background], paddings[padding], className),
6987
- children
6988
- }
6266
+ ref,
6267
+ "data-fluid-animate": shouldAnimate ? "" : void 0,
6268
+ className: cn(
6269
+ shouldAnimate && "opacity-0",
6270
+ active && ANIMATION_CLASSES[animation],
6271
+ className
6272
+ ),
6273
+ style: active ? animTimingStyle(delay, duration) : void 0
6274
+ },
6275
+ children
6989
6276
  );
6990
6277
  }
6991
- var maxWidthClasses = {
6992
- sm: "max-w-screen-sm",
6993
- md: "max-w-screen-md",
6994
- lg: "max-w-screen-lg",
6995
- xl: "max-w-screen-xl",
6996
- "2xl": "max-w-screen-2xl",
6997
- "4xl": "max-w-4xl",
6998
- "5xl": "max-w-5xl",
6999
- "6xl": "max-w-6xl",
7000
- "7xl": "max-w-7xl",
7001
- full: "max-w-full"
7002
- };
7003
- function Container({
6278
+ function FadeIn(props) {
6279
+ return /* @__PURE__ */ jsx(AnimateBase, { animation: "fadeIn", ...props });
6280
+ }
6281
+ function FadeInUp(props) {
6282
+ return /* @__PURE__ */ jsx(AnimateBase, { animation: "fadeInUp", ...props });
6283
+ }
6284
+ function ScaleIn(props) {
6285
+ return /* @__PURE__ */ jsx(AnimateBase, { animation: "scaleIn", ...props });
6286
+ }
6287
+ function SlideIn({ direction = "left", ...props }) {
6288
+ return /* @__PURE__ */ jsx(AnimateBase, { animation: SLIDE_MAP[direction], ...props });
6289
+ }
6290
+ function StaggerChildren({
7004
6291
  children,
6292
+ animation = "fadeInUp",
6293
+ staggerDelay = 100,
6294
+ initialDelay = 0,
6295
+ duration = 600,
6296
+ inView = false,
6297
+ inViewMargin,
6298
+ once = true,
6299
+ disabled = false,
6300
+ className,
6301
+ childClassName,
6302
+ as = "div"
6303
+ }) {
6304
+ const { ref, shouldAnimate, active } = useAnimationState({
6305
+ inView,
6306
+ inViewMargin,
6307
+ once,
6308
+ disabled
6309
+ });
6310
+ const items = Children.toArray(children);
6311
+ return createElement(
6312
+ as,
6313
+ { ref, className },
6314
+ items.map((child, i) => /* @__PURE__ */ jsx(
6315
+ "div",
6316
+ {
6317
+ "data-fluid-animate": shouldAnimate ? "" : void 0,
6318
+ className: cn(
6319
+ shouldAnimate && "opacity-0",
6320
+ active && ANIMATION_CLASSES[animation],
6321
+ childClassName
6322
+ ),
6323
+ style: active ? animTimingStyle(initialDelay + i * staggerDelay, duration) : void 0,
6324
+ children: child
6325
+ },
6326
+ i
6327
+ ))
6328
+ );
6329
+ }
6330
+ function AnimatedText({
6331
+ text,
6332
+ as = "div",
6333
+ animation = "fadeInUp",
6334
+ splitBy = "word",
6335
+ staggerDelay = 80,
6336
+ delay = 0,
6337
+ duration = 600,
6338
+ inView = false,
6339
+ inViewMargin,
6340
+ once = true,
6341
+ disabled = false,
6342
+ className,
6343
+ segmentClassName
6344
+ }) {
6345
+ const { ref, shouldAnimate, active } = useAnimationState({
6346
+ inView,
6347
+ inViewMargin,
6348
+ once,
6349
+ disabled
6350
+ });
6351
+ const segments = splitBy === "word" ? text.split(" ") : text.split("");
6352
+ let animIndex = 0;
6353
+ return createElement(
6354
+ as,
6355
+ { ref, className },
6356
+ segments.map((segment, i) => {
6357
+ if (splitBy === "character" && segment === " ") {
6358
+ return /* @__PURE__ */ jsx(Fragment$1, { children: "\xA0" }, i);
6359
+ }
6360
+ const idx = animIndex++;
6361
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
6362
+ splitBy === "word" && i > 0 && " ",
6363
+ /* @__PURE__ */ jsx(
6364
+ "span",
6365
+ {
6366
+ "data-fluid-animate": shouldAnimate ? "" : void 0,
6367
+ className: cn(
6368
+ "inline-block",
6369
+ shouldAnimate && "opacity-0",
6370
+ active && ANIMATION_CLASSES[animation],
6371
+ segmentClassName
6372
+ ),
6373
+ style: active ? animTimingStyle(delay + idx * staggerDelay, duration) : void 0,
6374
+ children: segment
6375
+ }
6376
+ )
6377
+ ] }, i);
6378
+ })
6379
+ );
6380
+ }
6381
+ function easeOutCubic(t) {
6382
+ return 1 - Math.pow(1 - t, 3);
6383
+ }
6384
+ function AnimatedCounter({
6385
+ from = 0,
6386
+ to,
6387
+ duration = 2e3,
6388
+ delay = 0,
6389
+ locale,
6390
+ prefix,
6391
+ suffix,
6392
+ decimals = 0,
6393
+ formatter,
6394
+ inView = false,
6395
+ inViewMargin,
6396
+ once = true,
6397
+ disabled = false,
7005
6398
  className,
7006
- maxWidth = "7xl"
6399
+ as = "span"
7007
6400
  }) {
7008
- const isFullWidth = maxWidth === "full";
7009
- const baseClass = isFullWidth ? "w-full px-4 sm:px-6 lg:px-10" : "mx-auto px-4 sm:px-6 lg:px-8";
7010
- return /* @__PURE__ */ jsx("div", { className: cn(baseClass, !isFullWidth && maxWidthClasses[maxWidth], className), children });
6401
+ const ref = useRef(null);
6402
+ const isInView = useInView(ref, {
6403
+ margin: inViewMargin,
6404
+ once,
6405
+ enabled: inView && !disabled
6406
+ });
6407
+ const active = !disabled && (!inView || isInView);
6408
+ const [count, setCount] = useState(from);
6409
+ const hasStarted = useRef(false);
6410
+ useEffect(() => {
6411
+ if (disabled) {
6412
+ setCount(to);
6413
+ return;
6414
+ }
6415
+ if (!active || hasStarted.current) return;
6416
+ hasStarted.current = true;
6417
+ if (typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
6418
+ setCount(to);
6419
+ return;
6420
+ }
6421
+ const timeout = setTimeout(() => {
6422
+ const start = performance.now();
6423
+ const step = (now) => {
6424
+ const elapsed = now - start;
6425
+ const progress = Math.min(elapsed / duration, 1);
6426
+ const eased = easeOutCubic(progress);
6427
+ const current = from + (to - from) * eased;
6428
+ setCount(
6429
+ decimals > 0 ? Number(current.toFixed(decimals)) : Math.round(current)
6430
+ );
6431
+ if (progress < 1) requestAnimationFrame(step);
6432
+ };
6433
+ requestAnimationFrame(step);
6434
+ }, delay);
6435
+ return () => clearTimeout(timeout);
6436
+ }, [active, disabled, from, to, duration, delay, decimals]);
6437
+ const formatValue = (v) => {
6438
+ if (formatter) return formatter(v);
6439
+ if (locale)
6440
+ return v.toLocaleString(locale, {
6441
+ minimumFractionDigits: decimals,
6442
+ maximumFractionDigits: decimals
6443
+ });
6444
+ if (decimals > 0) return v.toFixed(decimals);
6445
+ return String(v);
6446
+ };
6447
+ return createElement(
6448
+ as,
6449
+ { ref, className },
6450
+ /* @__PURE__ */ jsxs(Fragment, { children: [
6451
+ prefix,
6452
+ formatValue(count),
6453
+ suffix
6454
+ ] })
6455
+ );
7011
6456
  }
7012
6457
 
7013
- export { AccordionSection, ActionDropdown, ActionTooltip, ApiPagination, ButtonTooltip, CalendarDayDetail, CalendarWithDetail, CardWrapper, CheckboxDropdown, CheckboxInput, ClientSubmitButton, CollapsibleCard, CollapsibleSection, CollapsibleWrapper, ComboboxInput, CompactInput, CompactNumberInput, CompactSelect, CompactSlugField, CompactTagChoice, CompactTextarea, ConfirmDialog, ConfirmSheet, Container, CopyButton, CopyCodeBlock, CopyText, CustomPagination, DataCard, DataTable, DateInput, DateRangeFilter, DateRangeInput, DeleteConfirmDialog, DialogWrapper, DisplayHeading, DraggableCard, DropdownWrapper, DynamicTabs, ErrorState, ErrorStateInline, EventCalendar, FacebookIcon, FaqAccordion, FeatureItem, Field13 as Field, FormDialog, FormErrorSummary, FormInput, FormSheet, FormTextarea, GoogleIcon, IconItemMedia, IconTooltip, InfoAlert, InfoRow, InfoTooltip, InstagramIcon, LoadingCard, ModeToggle, PaginationInfo, PhoneInput, Pill, PillAvatar, PillAvatarGroup, PillButton, PillDelta, PillIcon, PillIndicator, PillStatus, RadioDropdown, RadioInput, ResponsiveSplitLayout, search_exports as Search, SearchProvider, Section, SelectDropdown, SelectInput, SheetWrapper, SimpleTable, SkeletonCard, SkeletonGrid, SkeletonList, SkeletonTable, SlugField, StatsCard, SwitchInput, TabContent, TabTrigger, TableWrapper, TabsWrapper, TagChoiceInput, TagInput, Thumbnail, TooltipWrapper, TwitterXIcon, WhatsAppIcon, buildFilterParams, buildListingStatusParams, buildSearchParams, clearSearchAndFilterParams, cn, generateSlug, generateSlug2 as generateSlugCompact, getApiParams, useBaseSearch, useIsMobile, useMediaQuery, useScrollDetection, useSearch };
6458
+ export { AccordionSection, ActionDropdown, ActionTooltip, AnimatedCounter, AnimatedText, ApiPagination, ButtonTooltip, CalendarDayDetail, CalendarWithDetail, CardWrapper, CheckboxDropdown, CheckboxInput, CollapsibleCard, CollapsibleSection, CollapsibleWrapper, ComboboxInput, ConfirmDialog, CopyButton, CopyCodeBlock, CopyText, CustomPagination, DEFAULT_COUNTRIES, DataCard, DataTable, DateInput, DateRangeFilter, DateRangeInput, DeleteConfirmDialog, DialogWrapper, DisplayHeading, DraggableCard, DropdownWrapper, DynamicTabs, EmptyState, EmptyStateNoData, EmptyStateNoResults, EmptyStateNotFound, ErrorState, ErrorStateInline, EventCalendar, FacebookIcon, FadeIn, FadeInUp, FaqAccordion, FeatureItem, FeatureList, FormDialog, FormErrorSummary, FormInput, FormTextarea, GoogleIcon, IconItemMedia, IconTooltip, InfoAlert, InfoRow, InfoTooltip, InstagramIcon, LoadingCard, LoadingOverlay, LoadingState, ModeToggle, PaginationInfo, PhoneInput, Pill, PillAvatar, PillAvatarGroup, PillButton, PillDelta, PillIcon, PillIndicator, PillStatus, RadioDropdown, RadioInput, ResponsiveSplitLayout, ScaleIn, SelectDropdown, SelectInput, SimpleTable, SkeletonCard, SkeletonGrid, SkeletonList, SkeletonTable, SlideIn, SlugField, StaggerChildren, StatsCard, StatusBanner, StepContent, Stepper, SwitchInput, TTL, TabContent, TabTrigger, TableWrapper, TabsWrapper, TagChoiceInput, TagInput, Thumbnail, TooltipWrapper, TwitterXIcon, WhatsAppIcon, buildFilterParams, buildListingStatusParams, buildSearchParams, clearSearchAndFilterParams, clearStorage, generateSlug, generateUUID, getApiParams, getStorageItem, isStorageEmpty, removeStorageItem, setStorageItem, storage, useBaseSearch, useCopyToClipboard, useDebounce, useDebouncedCallback, useInView, useLocalStorage, useMediaQuery, useScrollDetection };
7014
6459
  //# sourceMappingURL=index.js.map
7015
6460
  //# sourceMappingURL=index.js.map