@classytic/fluid 0.1.1 → 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, ChevronsUpDown, 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,33 +26,113 @@ 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';
43
44
  import { Calendar } from '@/components/ui/calendar';
45
+ import { Combobox, ComboboxInput as ComboboxInput$1, ComboboxContent, ComboboxEmpty, ComboboxList, ComboboxItem } from '@/components/ui/combobox';
44
46
  import { startOfMonth, endOfMonth, eachDayOfInterval, getDay, isSameDay, subMonths, addMonths, format, isSameMonth, isValid } from 'date-fns';
45
47
 
46
- var __defProp = Object.defineProperty;
47
- var __export = (target, all) => {
48
- for (var name in all)
49
- __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
50
135
  };
51
- function cn(...inputs) {
52
- return twMerge(clsx(inputs));
53
- }
54
136
 
55
137
  // src/lib/filter-utils.ts
56
138
  function buildFilterParams(filters, filterConfig) {
@@ -116,20 +198,6 @@ function getApiParams(searchParams) {
116
198
  }
117
199
  return params;
118
200
  }
119
- var MOBILE_BREAKPOINT = 768;
120
- function useIsMobile() {
121
- const [isMobile, setIsMobile] = React5.useState(void 0);
122
- React5.useEffect(() => {
123
- const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
124
- const onChange = () => {
125
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
126
- };
127
- mql.addEventListener("change", onChange);
128
- setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
129
- return () => mql.removeEventListener("change", onChange);
130
- }, []);
131
- return !!isMobile;
132
- }
133
201
  function useBaseSearch(config) {
134
202
  const {
135
203
  basePath,
@@ -170,9 +238,12 @@ function useBaseSearch(config) {
170
238
  });
171
239
  return initialFilters;
172
240
  });
241
+ const stableConfig = {
242
+ searchFields,
243
+ filterFields};
173
244
  const handleSearch = useCallback(() => {
174
245
  const params = new URLSearchParams(searchParams);
175
- clearSearchAndFilterParams(params, config);
246
+ clearSearchAndFilterParams(params, stableConfig);
176
247
  const searchParamsNew = buildSearchParams(searchType, searchValue, searchFields);
177
248
  for (const [key, value] of searchParamsNew) {
178
249
  params.set(key, value);
@@ -182,20 +253,10 @@ function useBaseSearch(config) {
182
253
  params.set(key, value);
183
254
  }
184
255
  router.push(`${basePath}?${params.toString()}`);
185
- }, [
186
- searchType,
187
- searchValue,
188
- filters,
189
- searchFields,
190
- filterFields,
191
- searchParams,
192
- router,
193
- basePath,
194
- config
195
- ]);
256
+ }, [searchType, searchValue, filters, searchFields, filterFields, searchParams, router, basePath, defaultSearchType]);
196
257
  const clearSearch = useCallback(() => {
197
258
  const params = new URLSearchParams(searchParams);
198
- clearSearchAndFilterParams(params, config);
259
+ clearSearchAndFilterParams(params, stableConfig);
199
260
  setSearchValue("");
200
261
  setSearchType(defaultSearchType);
201
262
  const resetFilters = {};
@@ -205,7 +266,7 @@ function useBaseSearch(config) {
205
266
  setFilters(resetFilters);
206
267
  const next = params.toString();
207
268
  router.push(next ? `${basePath}?${next}` : `${basePath}`);
208
- }, [searchParams, router, basePath, config, defaultSearchType, filterFields]);
269
+ }, [searchParams, router, basePath, defaultSearchType, searchFields, filterFields]);
209
270
  const getSearchParamsForApi = useCallback(() => {
210
271
  return getApiParams(searchParams);
211
272
  }, [searchParams]);
@@ -258,6 +319,12 @@ var useScrollDetection = (ref, delay = 100) => {
258
319
  canScrollRight: false,
259
320
  isScrollable: false
260
321
  });
322
+ const timeoutRef = useRef(void 0);
323
+ useEffect(() => {
324
+ return () => {
325
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
326
+ };
327
+ }, []);
261
328
  const checkScroll = useCallback(() => {
262
329
  const scrollContainer = ref.current?.querySelector(
263
330
  '[data-slot="scroll-area-viewport"]'
@@ -275,11 +342,105 @@ var useScrollDetection = (ref, delay = 100) => {
275
342
  });
276
343
  }, [ref]);
277
344
  const debouncedCheckScroll = useCallback(() => {
278
- const timeoutId = setTimeout(checkScroll, delay);
279
- return () => clearTimeout(timeoutId);
345
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
346
+ timeoutRef.current = setTimeout(checkScroll, delay);
280
347
  }, [checkScroll, delay]);
281
348
  return { ...scrollState, checkScroll: debouncedCheckScroll };
282
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
+ }
283
444
  var AccordionSection = memo(function AccordionSection2({
284
445
  title,
285
446
  icon,
@@ -308,13 +469,13 @@ var FaqAccordion = memo(function FaqAccordion2({
308
469
  items,
309
470
  defaultOpen,
310
471
  className,
311
- openMultiple = false
472
+ multiple = false
312
473
  }) {
313
474
  return /* @__PURE__ */ jsx(
314
475
  Accordion,
315
476
  {
316
477
  defaultValue: defaultOpen ? [defaultOpen] : [],
317
- openMultiple,
478
+ multiple,
318
479
  className: cn("w-full", className),
319
480
  children: items.map((item) => /* @__PURE__ */ jsxs(AccordionItem, { value: item.id, children: [
320
481
  /* @__PURE__ */ jsx(AccordionTrigger, { className: "text-left", children: item.question }),
@@ -701,6 +862,29 @@ function ApiPagination({
701
862
  }
702
863
  );
703
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
+ };
704
888
  function CardWrapper({
705
889
  title,
706
890
  description,
@@ -715,48 +899,25 @@ function CardWrapper({
715
899
  hideHeader = false,
716
900
  ...props
717
901
  }) {
718
- const variants = {
719
- default: "",
720
- outline: "border-2",
721
- ghost: "border-0 shadow-none bg-transparent",
722
- elevated: "shadow-lg border-0",
723
- primary: "border-primary/20 bg-primary/5",
724
- secondary: "border-secondary/20 bg-secondary/5",
725
- destructive: "border-destructive/20 bg-destructive/5",
726
- success: "border-green-500/20 bg-green-500/5",
727
- warning: "border-yellow-500/20 bg-yellow-500/5"
728
- };
729
- const sizes2 = {
730
- sm: "p-3",
731
- default: "p-6",
732
- lg: "p-8",
733
- xl: "p-10"
734
- };
735
- const contentSizes = {
736
- sm: "pt-3",
737
- default: "pt-6",
738
- lg: "pt-8",
739
- xl: "pt-10"
740
- };
741
- return /* @__PURE__ */ jsxs(Card, { className: cn(variants[variant], className), ...props, children: [
742
- !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: [
743
904
  title && /* @__PURE__ */ jsx(CardTitle, { className: "text-lg font-semibold", children: title }),
744
905
  description && /* @__PURE__ */ jsx(CardDescription, { children: description })
745
906
  ] }),
746
907
  /* @__PURE__ */ jsx(
747
908
  CardContent,
748
909
  {
749
- className: cn(hideHeader ? sizes2[size] : contentSizes[size], contentClassName),
910
+ className: cn(hideHeader ? CARD_SIZES[size] : CARD_CONTENT_SIZES[size], contentClassName),
750
911
  children
751
912
  }
752
913
  ),
753
- 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 }) })
754
915
  ] });
755
916
  }
756
917
  function DataCard({ title, data, className, ...props }) {
757
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: [
758
919
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: item.label }),
759
- /* @__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 })
760
921
  ] }, index)) }) });
761
922
  }
762
923
  function LoadingCard({ title, description, className, ...props }) {
@@ -765,6 +926,27 @@ function LoadingCard({ title, description, className, ...props }) {
765
926
  /* @__PURE__ */ jsx("span", { className: "ml-2", children: "Loading..." })
766
927
  ] }) });
767
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
+ };
768
950
  function StatsCard({
769
951
  title,
770
952
  value,
@@ -776,31 +958,10 @@ function StatsCard({
776
958
  iconClassName,
777
959
  ...props
778
960
  }) {
779
- const cardVariants = {
780
- default: "",
781
- success: "bg-green-50 border-green-200 dark:bg-green-950/30 dark:border-green-900",
782
- warning: "bg-yellow-50 border-yellow-200 dark:bg-yellow-950/30 dark:border-yellow-900",
783
- danger: "bg-red-50 border-red-200 dark:bg-red-950/30 dark:border-red-900",
784
- info: "bg-blue-50 border-blue-200 dark:bg-blue-950/30 dark:border-blue-900"
785
- };
786
- const iconVariants = {
787
- default: "text-muted-foreground",
788
- success: "text-green-600 dark:text-green-400",
789
- warning: "text-yellow-600 dark:text-yellow-400",
790
- danger: "text-red-600 dark:text-red-400",
791
- info: "text-blue-600 dark:text-blue-400"
792
- };
793
- const iconWrapperVariants = {
794
- default: "bg-muted border border-border",
795
- success: "bg-green-100/50 dark:bg-green-900/30",
796
- warning: "bg-yellow-100/50 dark:bg-yellow-900/30",
797
- danger: "bg-red-100/50 dark:bg-red-900/30",
798
- info: "bg-blue-100/50 dark:bg-blue-900/30"
799
- };
800
961
  return /* @__PURE__ */ jsxs(
801
962
  CardWrapper,
802
963
  {
803
- className: cn("relative overflow-hidden", cardVariants[statsVariant], className),
964
+ className: cn("relative overflow-hidden", STATS_CARD_VARIANTS[statsVariant], className),
804
965
  size: "sm",
805
966
  hideHeader: true,
806
967
  ...props,
@@ -813,8 +974,8 @@ function StatsCard({
813
974
  ] }),
814
975
  icon && /* @__PURE__ */ jsx("div", { className: cn(
815
976
  "p-2 rounded-md",
816
- iconWrapperVariants[statsVariant],
817
- iconVariants[statsVariant],
977
+ STATS_ICON_WRAPPER_VARIANTS[statsVariant],
978
+ STATS_ICON_VARIANTS[statsVariant],
818
979
  iconClassName
819
980
  ), children: icon })
820
981
  ] }),
@@ -965,39 +1126,6 @@ function SkeletonGrid({
965
1126
  };
966
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)) });
967
1128
  }
968
- function ClientSubmitButton({
969
- children,
970
- disabled,
971
- loading = false,
972
- loadingText,
973
- className,
974
- variant,
975
- size,
976
- form,
977
- ...props
978
- }) {
979
- const isDisabled = loading || disabled;
980
- const content = loading && loadingText ? loadingText : children;
981
- return /* @__PURE__ */ jsxs(
982
- Button,
983
- {
984
- type: "submit",
985
- form,
986
- "aria-disabled": isDisabled,
987
- "aria-busy": loading,
988
- className: cn("relative", className),
989
- disabled: isDisabled,
990
- variant,
991
- size,
992
- ...props,
993
- children: [
994
- content,
995
- loading && /* @__PURE__ */ jsx("span", { className: "animate-spin absolute right-4", children: /* @__PURE__ */ jsx(LoaderIcon, {}) }),
996
- /* @__PURE__ */ jsx("span", { "aria-live": "polite", className: "sr-only", role: "status", children: loading ? "Loading" : "Submit form" })
997
- ]
998
- }
999
- );
1000
- }
1001
1129
  function CollapsibleWrapper({
1002
1130
  children,
1003
1131
  trigger,
@@ -1083,10 +1211,11 @@ function CollapsibleCard({
1083
1211
  CollapsibleTrigger,
1084
1212
  {
1085
1213
  render: /* @__PURE__ */ jsx(
1086
- "div",
1214
+ "button",
1087
1215
  {
1216
+ type: "button",
1088
1217
  className: cn(
1089
- "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",
1090
1219
  headerClassName
1091
1220
  )
1092
1221
  }
@@ -1126,7 +1255,10 @@ function CollapsibleSection({
1126
1255
  defaultOpen,
1127
1256
  triggerVariant: "ghost",
1128
1257
  triggerSize: "sm",
1129
- 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
+ ),
1130
1262
  contentClassName: cn("pl-4 mt-1", contentClassName),
1131
1263
  className: cn("space-y-1", className),
1132
1264
  ...props,
@@ -1168,7 +1300,7 @@ function ConfirmDialog({
1168
1300
  }
1169
1301
  };
1170
1302
  const triggerChildren = trigger?.props?.children;
1171
- const triggerElement = trigger ? React5.cloneElement(trigger, { children: void 0 }) : null;
1303
+ const triggerElement = trigger ? React3.cloneElement(trigger, { children: void 0 }) : null;
1172
1304
  return /* @__PURE__ */ jsxs(AlertDialog, { open, onOpenChange, ...props, children: [
1173
1305
  triggerElement && /* @__PURE__ */ jsx(AlertDialogTrigger, { render: triggerElement, children: triggerChildren }),
1174
1306
  /* @__PURE__ */ jsxs(AlertDialogContent, { className: cn("max-w-md", className), children: [
@@ -1310,104 +1442,626 @@ function ErrorStateInline({
1310
1442
  }
1311
1443
  );
1312
1444
  }
1313
- async function copyToClipboard(text, options) {
1314
- try {
1315
- await navigator.clipboard.writeText(text);
1316
- return true;
1317
- } catch {
1318
- 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."
1319
1460
  }
1320
- }
1321
- function CopyButton({
1322
- value,
1461
+ };
1462
+ function EmptyState({
1463
+ title = "Nothing here",
1464
+ description,
1465
+ icon: IconProp = InboxIcon,
1466
+ action,
1467
+ secondaryAction,
1468
+ variant = "default",
1323
1469
  className,
1324
- size = "sm",
1325
- variant = "ghost",
1326
- showToast = true,
1327
- toastMessage = "Copied to clipboard",
1328
- errorMessage = "Failed to copy to clipboard",
1329
- timeout = 2e3,
1330
- children,
1331
- ...props
1470
+ children
1332
1471
  }) {
1333
- const [copied, setCopied] = useState(false);
1334
- const handleCopy = async () => {
1335
- if (!value) return;
1336
- const success = await copyToClipboard(value);
1337
- if (success) {
1338
- setCopied(true);
1339
- 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
1340
1482
  }
1341
- };
1342
- return /* @__PURE__ */ jsx(
1343
- 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",
1344
1505
  {
1345
- variant,
1346
- size,
1347
- className: cn("h-6 w-6 p-0", className),
1348
- onClick: handleCopy,
1349
- disabled: !value,
1350
- ...props,
1351
- 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
+ ]
1352
1549
  }
1353
1550
  );
1354
1551
  }
1355
- function CopyText({
1356
- value,
1357
- displayValue,
1358
- className,
1359
- textClassName,
1360
- buttonClassName,
1361
- maxLength = 30,
1362
- showButton = true,
1363
- ...buttonProps
1364
- }) {
1365
- const truncatedValue = displayValue || (value && value.length > maxLength ? `${value.substring(0, maxLength)}...` : value || "N/A");
1366
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
1367
- /* @__PURE__ */ jsx("span", { className: cn("font-medium", textClassName), title: value || "N/A", children: truncatedValue }),
1368
- showButton && value && /* @__PURE__ */ jsx(CopyButton, { value, className: buttonClassName, ...buttonProps })
1369
- ] });
1552
+ function EmptyStateNoResults(props) {
1553
+ return /* @__PURE__ */ jsx(EmptyState, { ...PRESETS.noResults, ...props });
1370
1554
  }
1371
- function CopyCodeBlock({
1372
- value,
1373
- className,
1374
- language,
1375
- showLineNumbers = false,
1376
- ...buttonProps
1377
- }) {
1378
- return /* @__PURE__ */ jsxs("div", { className: cn("relative group", className), children: [
1379
- /* @__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 }) }),
1380
- /* @__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 }) })
1381
- ] });
1555
+ function EmptyStateNoData(props) {
1556
+ return /* @__PURE__ */ jsx(EmptyState, { ...PRESETS.noData, ...props });
1382
1557
  }
1383
- var ScrollButton = ({ direction, onClick, visible, className }) => {
1384
- if (!visible) return null;
1385
- const handleClick = (e) => {
1386
- e.preventDefault();
1387
- e.stopPropagation();
1388
- onClick();
1389
- };
1390
- return /* @__PURE__ */ jsx(
1391
- "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",
1392
1603
  {
1393
- type: "button",
1394
1604
  className: cn(
1395
- "absolute top-1/2 -translate-y-1/2 z-50",
1396
- "flex items-center justify-center",
1397
- "size-10 rounded-md shadow-lg border-2 border-border",
1398
- "bg-background hover:bg-muted",
1399
- "transition-transform duration-200",
1400
- "hover:scale-105 active:scale-95",
1401
- direction === "left" ? "left-2" : "right-2",
1605
+ "flex flex-col items-center justify-center gap-3 py-12 px-6",
1402
1606
  className
1403
1607
  ),
1404
- onClick: handleClick,
1405
- onMouseDown: (e) => e.stopPropagation(),
1406
- "aria-label": `Scroll ${direction}`,
1407
- 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
+ ]
1408
1612
  }
1409
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
+ }
1410
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
+ });
1411
2065
  function DataTable({
1412
2066
  columns,
1413
2067
  data,
@@ -1416,7 +2070,9 @@ function DataTable({
1416
2070
  enableSorting = false,
1417
2071
  enableRowSelection = false,
1418
2072
  onRowSelectionChange,
1419
- className
2073
+ className,
2074
+ loadingState: customLoadingState,
2075
+ emptyState: customEmptyState
1420
2076
  }) {
1421
2077
  const [sorting, setSorting] = useState([]);
1422
2078
  const [rowSelection, setRowSelection] = useState({});
@@ -1498,14 +2154,14 @@ function DataTable({
1498
2154
  const timer = setTimeout(checkScroll, 150);
1499
2155
  return () => clearTimeout(timer);
1500
2156
  }, [data, checkScroll]);
1501
- const loadingState = useMemo(
2157
+ const defaultLoadingState = useMemo(
1502
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: [
1503
2159
  /* @__PURE__ */ jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-2 border-primary border-t-transparent" }),
1504
2160
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Loading data..." })
1505
2161
  ] }) }),
1506
2162
  []
1507
2163
  );
1508
- const emptyState = useMemo(
2164
+ const defaultEmptyState = useMemo(
1509
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: [
1510
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" }) }),
1511
2167
  /* @__PURE__ */ jsx("p", { className: "text-lg font-medium text-foreground mb-1", children: "No results found" }),
@@ -1514,7 +2170,7 @@ function DataTable({
1514
2170
  [columns.length]
1515
2171
  );
1516
2172
  if (isLoading) {
1517
- return loadingState;
2173
+ return /* @__PURE__ */ jsx(Fragment, { children: customLoadingState || defaultLoadingState });
1518
2174
  }
1519
2175
  return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col h-full gap-4", className), children: [
1520
2176
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 rounded-lg border overflow-hidden bg-background shadow-sm relative", children: [
@@ -1574,7 +2230,7 @@ function DataTable({
1574
2230
  ))
1575
2231
  },
1576
2232
  row.id
1577
- )) : emptyState })
2233
+ )) : customEmptyState ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: "h-32 text-center", children: customEmptyState }) }) : defaultEmptyState })
1578
2234
  ] }) }),
1579
2235
  /* @__PURE__ */ jsx(ScrollBar, { orientation: "horizontal" })
1580
2236
  ] }),
@@ -1610,12 +2266,12 @@ function DataTable({
1610
2266
  ] });
1611
2267
  }
1612
2268
  var SIZE_VARIANTS = {
1613
- sm: "sm:!max-w-sm",
1614
- default: "sm:!max-w-md",
1615
- lg: "sm:!max-w-lg md:!max-w-2xl",
1616
- xl: "sm:!max-w-2xl md:!max-w-4xl",
1617
- "2xl": "sm:!max-w-4xl md:!max-w-6xl",
1618
- 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]"
1619
2275
  };
1620
2276
  function DialogWrapper({
1621
2277
  open,
@@ -1642,7 +2298,7 @@ function DialogWrapper({
1642
2298
  DialogContent,
1643
2299
  {
1644
2300
  showCloseButton: !hideCloseButton,
1645
- className: cn(SIZE_VARIANTS[size], contentClassName, className),
2301
+ className: cn("max-w-none", SIZE_VARIANTS[size], contentClassName, className),
1646
2302
  children: [
1647
2303
  !hideHeader && /* @__PURE__ */ jsxs(DialogHeader, { className: cn("space-y-2", headerClassName), children: [
1648
2304
  hideTitle ? /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: title || "Dialog" }) : /* @__PURE__ */ jsx(DialogTitle, { children: title || "Dialog" }),
@@ -1669,18 +2325,10 @@ function FormDialog({
1669
2325
  submitDisabled = false,
1670
2326
  ...props
1671
2327
  }) {
1672
- const footer = /* @__PURE__ */ jsxs(Fragment, { children: [
1673
- /* @__PURE__ */ jsx(
1674
- Button,
1675
- {
1676
- variant: "outline",
1677
- onClick: onCancel || (() => onOpenChange(false)),
1678
- disabled: isLoading,
1679
- children: cancelText
1680
- }
1681
- ),
1682
- /* @__PURE__ */ jsx(Button, { onClick: onSubmit, disabled: isLoading || submitDisabled, children: isLoading ? "Loading..." : submitText })
1683
- ] });
2328
+ const handleSubmit = (e) => {
2329
+ e.preventDefault();
2330
+ onSubmit?.(e);
2331
+ };
1684
2332
  return /* @__PURE__ */ jsx(
1685
2333
  DialogWrapper,
1686
2334
  {
@@ -1688,16 +2336,30 @@ function FormDialog({
1688
2336
  onOpenChange,
1689
2337
  title,
1690
2338
  description,
1691
- footer,
1692
2339
  ...props,
1693
- children
1694
- }
1695
- );
1696
- }
1697
- function DropdownWrapper({
1698
- trigger,
1699
- children,
1700
- 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",
1701
2363
  side = "bottom",
1702
2364
  sideOffset = 4,
1703
2365
  className,
@@ -1983,11 +2645,11 @@ function RadioDropdown({
1983
2645
  )
1984
2646
  ] });
1985
2647
  }
1986
- function InfoRow({ label, value, copyable = false, icon: Icon2 }) {
2648
+ function InfoRow({ label, value, copyable = false, icon: Icon }) {
1987
2649
  if (!value && value !== 0) return null;
1988
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: [
1989
2651
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
1990
- 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" }),
1991
2653
  /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-muted-foreground truncate", children: label })
1992
2654
  ] }),
1993
2655
  /* @__PURE__ */ jsx("div", { className: "sm:text-right min-w-0 flex-shrink-0", children: copyable ? /* @__PURE__ */ jsx(
@@ -2032,7 +2694,7 @@ var iconItemMediaVariants = cva(
2032
2694
  }
2033
2695
  }
2034
2696
  );
2035
- var IconItemMedia = React5.memo(function IconItemMedia2({
2697
+ var IconItemMedia = React3.memo(function IconItemMedia2({
2036
2698
  icon,
2037
2699
  iconBg = "primary",
2038
2700
  iconSize = "md",
@@ -2052,7 +2714,7 @@ var IconItemMedia = React5.memo(function IconItemMedia2({
2052
2714
  );
2053
2715
  });
2054
2716
  IconItemMedia.displayName = "IconItemMedia";
2055
- var FeatureItem = React5.memo(function FeatureItem2({
2717
+ var FeatureItem = React3.memo(function FeatureItem2({
2056
2718
  icon,
2057
2719
  iconBg = "primary",
2058
2720
  iconSize = "md",
@@ -2094,7 +2756,10 @@ var FeatureItem = React5.memo(function FeatureItem2({
2094
2756
  icon,
2095
2757
  iconBg,
2096
2758
  iconSize,
2097
- className: cn(layout === "vertical" ? "" : "shrink-0", iconClassName)
2759
+ className: cn(
2760
+ layout === "vertical" ? "" : "shrink-0",
2761
+ iconClassName
2762
+ )
2098
2763
  }
2099
2764
  ),
2100
2765
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 flex-1", children: [
@@ -2172,10 +2837,50 @@ var FeatureItem = React5.memo(function FeatureItem2({
2172
2837
  );
2173
2838
  });
2174
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";
2175
2880
  function ModeToggle() {
2176
2881
  const { theme, setTheme } = useTheme();
2177
- const [mounted, setMounted] = React5.useState(false);
2178
- React5.useEffect(() => {
2882
+ const [mounted, setMounted] = React3.useState(false);
2883
+ React3.useEffect(() => {
2179
2884
  setMounted(true);
2180
2885
  }, []);
2181
2886
  if (!mounted) {
@@ -2197,7 +2902,7 @@ function ModeToggle() {
2197
2902
  ] }) })
2198
2903
  ] });
2199
2904
  }
2200
- var COUNTRIES = [
2905
+ var DEFAULT_COUNTRIES = [
2201
2906
  { code: "GB", name: "United Kingdom", dialCode: "+44", flag: "\u{1F1EC}\u{1F1E7}" },
2202
2907
  { code: "US", name: "United States", dialCode: "+1", flag: "\u{1F1FA}\u{1F1F8}" },
2203
2908
  { code: "IE", name: "Ireland", dialCode: "+353", flag: "\u{1F1EE}\u{1F1EA}" },
@@ -2249,145 +2954,147 @@ var COUNTRIES = [
2249
2954
  { code: "RU", name: "Russia", dialCode: "+7", flag: "\u{1F1F7}\u{1F1FA}" },
2250
2955
  { code: "IL", name: "Israel", dialCode: "+972", flag: "\u{1F1EE}\u{1F1F1}" }
2251
2956
  ];
2252
- var getCountryByCode = (code) => COUNTRIES.find((c) => c.code === code);
2253
- var PhoneInput = React5.forwardRef(
2254
- ({
2255
- className,
2256
- onChange,
2257
- value,
2258
- defaultCountry = "GB",
2259
- disabled,
2260
- placeholder = "Phone number",
2261
- ...props
2262
- }, ref) => {
2263
- const [isOpen, setIsOpen] = React5.useState(false);
2264
- const [searchValue, setSearchValue] = React5.useState("");
2265
- const parseValue = React5.useCallback(
2266
- (val) => {
2267
- const valString = val ? String(val) : "";
2268
- if (!valString) {
2269
- return {
2270
- country: getCountryByCode(defaultCountry) || COUNTRIES[0],
2271
- number: ""
2272
- };
2273
- }
2274
- const cleanVal = valString.replace(/\s/g, "");
2275
- for (const country2 of COUNTRIES) {
2276
- if (cleanVal.startsWith(country2.dialCode)) {
2277
- return {
2278
- country: country2,
2279
- number: cleanVal.slice(country2.dialCode.length)
2280
- };
2281
- }
2282
- }
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) {
2283
2978
  return {
2284
- country: getCountryByCode(defaultCountry) || COUNTRIES[0],
2285
- number: cleanVal.replace(/^\+/, "")
2979
+ country: getCountryByCode(defaultCountry) || countries[0],
2980
+ number: ""
2286
2981
  };
2287
- },
2288
- [defaultCountry]
2289
- );
2290
- const { country, number } = parseValue(value);
2291
- const [selectedCountry, setSelectedCountry] = React5.useState(country);
2292
- React5.useEffect(() => {
2293
- const parsed = parseValue(value);
2294
- setSelectedCountry(parsed.country);
2295
- }, [value, parseValue]);
2296
- const handleCountryChange = (newCountry) => {
2297
- setSelectedCountry(newCountry);
2298
- setIsOpen(false);
2299
- if (number) {
2300
- onChange?.(newCountry.dialCode + number);
2301
2982
  }
2302
- };
2303
- const handleNumberChange = (e) => {
2304
- const newNumber = e.target.value.replace(/[^\d]/g, "");
2305
- if (newNumber) {
2306
- onChange?.(selectedCountry.dialCode + newNumber);
2307
- } else {
2308
- 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
+ }
2309
2991
  }
2310
- };
2311
- return /* @__PURE__ */ jsxs(InputGroup, { className, children: [
2312
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(
2313
- Popover,
2314
- {
2315
- open: isOpen,
2316
- modal: true,
2317
- onOpenChange: (open) => {
2318
- setIsOpen(open);
2319
- if (open) setSearchValue("");
2320
- },
2321
- children: [
2322
- /* @__PURE__ */ jsxs(
2323
- PopoverTrigger,
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: [
3051
+ /* @__PURE__ */ jsx(
3052
+ CommandInput,
2324
3053
  {
2325
- render: /* @__PURE__ */ jsx(
2326
- Button,
2327
- {
2328
- type: "button",
2329
- variant: "ghost",
2330
- className: "gap-1.5 rounded-none border-r px-3 focus:z-10 min-w-[90px] h-full",
2331
- disabled
2332
- }
2333
- ),
2334
- children: [
2335
- /* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: selectedCountry.flag }),
2336
- /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: selectedCountry.dialCode }),
2337
- /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5 opacity-50" })
2338
- ]
3054
+ value: searchValue,
3055
+ onValueChange: setSearchValue,
3056
+ placeholder: "Search country..."
2339
3057
  }
2340
3058
  ),
2341
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[280px] p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
2342
- /* @__PURE__ */ jsx(
2343
- 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,
2344
3065
  {
2345
- value: searchValue,
2346
- onValueChange: setSearchValue,
2347
- placeholder: "Search country..."
2348
- }
2349
- ),
2350
- /* @__PURE__ */ jsx(CommandList, { children: /* @__PURE__ */ jsxs(ScrollArea, { className: "h-64", children: [
2351
- /* @__PURE__ */ jsx(CommandEmpty, { children: "No country found." }),
2352
- /* @__PURE__ */ jsx(CommandGroup, { children: COUNTRIES.filter(
2353
- (c) => c.name.toLowerCase().includes(searchValue.toLowerCase()) || c.dialCode.includes(searchValue) || c.code.toLowerCase().includes(searchValue.toLowerCase())
2354
- ).map((c) => /* @__PURE__ */ jsxs(
2355
- CommandItem,
2356
- {
2357
- className: "gap-2 cursor-pointer",
2358
- onSelect: () => handleCountryChange(c),
2359
- value: `${c.name} ${c.code} ${c.dialCode}`,
2360
- children: [
2361
- /* @__PURE__ */ jsx("span", { className: "text-base", children: c.flag }),
2362
- /* @__PURE__ */ jsx("span", { className: "flex-1 text-sm", children: c.name }),
2363
- /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: c.dialCode })
2364
- ]
2365
- },
2366
- c.code
2367
- )) })
2368
- ] }) })
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
+ )) })
2369
3077
  ] }) })
2370
- ]
2371
- }
2372
- ) }),
2373
- /* @__PURE__ */ jsx(
2374
- InputGroupInput,
2375
- {
2376
- ref,
2377
- type: "tel",
2378
- inputMode: "numeric",
2379
- className: "rounded-s-none",
2380
- placeholder,
2381
- value: number,
2382
- onChange: handleNumberChange,
2383
- disabled,
2384
- ...props
2385
- }
2386
- )
2387
- ] });
2388
- }
2389
- );
2390
- 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
+ }
2391
3098
  function Pill({
2392
3099
  variant = "secondary",
2393
3100
  themed = false,
@@ -2467,8 +3174,8 @@ function PillDelta({ className, delta }) {
2467
3174
  }
2468
3175
  return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-3 text-rose-500", className) });
2469
3176
  }
2470
- function PillIcon({ icon: Icon2, className, ...props }) {
2471
- 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 });
2472
3179
  }
2473
3180
  function PillAvatarGroup({ children, className, ...props }) {
2474
3181
  return /* @__PURE__ */ jsx(
@@ -2601,7 +3308,16 @@ var TabContent = memo(function TabContent2({
2601
3308
  () => cn(padding && "px-6 py-4"),
2602
3309
  [padding]
2603
3310
  );
2604
- 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
+ );
2605
3321
  });
2606
3322
  var DynamicTabs = memo(function DynamicTabs2({
2607
3323
  tabs = [],
@@ -2859,203 +3575,6 @@ function ResponsiveSplitLayout({
2859
3575
  }
2860
3576
  );
2861
3577
  }
2862
- var SIZE_VARIANTS2 = {
2863
- sm: "sm:!max-w-md",
2864
- default: "w-full sm:!max-w-md md:!max-w-lg",
2865
- lg: "w-full sm:!max-w-lg md:!max-w-2xl lg:!max-w-4xl",
2866
- xl: "w-full sm:!max-w-2xl md:!max-w-4xl lg:!max-w-5xl",
2867
- full: "w-full !max-w-full",
2868
- mobile: "w-[85%] !max-w-sm",
2869
- "mobile-nav": "!w-[300px] sm:!w-[350px]"
2870
- };
2871
- var getPadding = (size, type = "default") => {
2872
- const isFullSize = size === "full";
2873
- if (type === "header" || type === "footer") {
2874
- return isFullSize ? "px-6 lg:px-8" : "px-4";
2875
- }
2876
- return isFullSize ? "p-6 lg:p-8" : "p-4";
2877
- };
2878
- var SheetWrapper = memo(function SheetWrapper2({
2879
- open,
2880
- onOpenChange,
2881
- title,
2882
- description,
2883
- children,
2884
- footer,
2885
- header,
2886
- side = "right",
2887
- size = "default",
2888
- modal = true,
2889
- className,
2890
- headerClassName,
2891
- contentClassName,
2892
- footerClassName,
2893
- innerClassName,
2894
- hideHeader = false,
2895
- hideTitle = false,
2896
- hideDescription = false,
2897
- hideCloseButton = false,
2898
- disableContentPadding = false
2899
- }) {
2900
- const computedClasses = useMemo(
2901
- () => ({
2902
- header: cn("border-b pb-4 pt-6", getPadding(size, "header"), headerClassName),
2903
- inner: cn(
2904
- "flex-1 overflow-y-auto",
2905
- !disableContentPadding && getPadding(size),
2906
- innerClassName
2907
- ),
2908
- footer: cn(
2909
- "border-t bg-muted/30 pt-4 pb-6 mt-auto",
2910
- getPadding(size, "footer"),
2911
- footerClassName
2912
- )
2913
- }),
2914
- [size, headerClassName, innerClassName, footerClassName, disableContentPadding]
2915
- );
2916
- const shouldHideTitle = !!header || hideTitle;
2917
- const shouldHideDescription = !!header || hideDescription;
2918
- return /* @__PURE__ */ jsx(Sheet, { open, onOpenChange, modal, children: /* @__PURE__ */ jsxs(
2919
- SheetContent,
2920
- {
2921
- side,
2922
- showCloseButton: !hideCloseButton,
2923
- className: cn(SIZE_VARIANTS2[size], "flex flex-col p-0", contentClassName, className),
2924
- children: [
2925
- !hideHeader && /* @__PURE__ */ jsxs(SheetHeader, { className: computedClasses.header, children: [
2926
- /* @__PURE__ */ jsx(SheetTitle, { className: shouldHideTitle ? "sr-only" : "", children: title || "Sheet" }),
2927
- description && /* @__PURE__ */ jsx(SheetDescription, { className: shouldHideDescription ? "sr-only" : "", children: description }),
2928
- header
2929
- ] }),
2930
- /* @__PURE__ */ jsx("div", { className: computedClasses.inner, children }),
2931
- footer && /* @__PURE__ */ jsx(SheetFooter, { className: computedClasses.footer, children: footer })
2932
- ]
2933
- }
2934
- ) });
2935
- });
2936
- var FormSheet = memo(function FormSheet2({
2937
- open,
2938
- onOpenChange,
2939
- title,
2940
- description,
2941
- children,
2942
- onSubmit,
2943
- onCancel,
2944
- submitLabel = "Submit",
2945
- cancelLabel = "Cancel",
2946
- submitDisabled = false,
2947
- submitLoading = false,
2948
- formId,
2949
- size = "lg",
2950
- ...props
2951
- }) {
2952
- const handleCancel = useCallback(() => {
2953
- onCancel?.();
2954
- onOpenChange?.(false);
2955
- }, [onCancel, onOpenChange]);
2956
- const footer = useMemo(
2957
- () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-2 w-full", children: [
2958
- /* @__PURE__ */ jsx(
2959
- Button,
2960
- {
2961
- type: "button",
2962
- variant: "outline",
2963
- className: "flex-1",
2964
- onClick: handleCancel,
2965
- disabled: submitDisabled || submitLoading,
2966
- children: cancelLabel
2967
- }
2968
- ),
2969
- /* @__PURE__ */ jsx(
2970
- ClientSubmitButton,
2971
- {
2972
- form: formId,
2973
- className: "flex-1",
2974
- disabled: submitDisabled,
2975
- loading: submitLoading,
2976
- loadingText: "Saving...",
2977
- children: submitLabel
2978
- }
2979
- )
2980
- ] }),
2981
- [cancelLabel, submitLabel, submitDisabled, submitLoading, formId, handleCancel]
2982
- );
2983
- return /* @__PURE__ */ jsx(
2984
- SheetWrapper,
2985
- {
2986
- open,
2987
- onOpenChange,
2988
- title,
2989
- description,
2990
- size,
2991
- footer,
2992
- ...props,
2993
- children
2994
- }
2995
- );
2996
- });
2997
- var ConfirmSheet = memo(function ConfirmSheet2({
2998
- open,
2999
- onOpenChange,
3000
- title = "Confirm Action",
3001
- description,
3002
- children,
3003
- onConfirm,
3004
- onCancel,
3005
- confirmLabel = "Confirm",
3006
- cancelLabel = "Cancel",
3007
- confirmVariant = "default",
3008
- confirmDisabled = false,
3009
- confirmLoading = false,
3010
- size = "sm",
3011
- ...props
3012
- }) {
3013
- const handleConfirm = useCallback(() => {
3014
- onConfirm?.();
3015
- }, [onConfirm]);
3016
- const handleCancel = useCallback(() => {
3017
- onCancel?.();
3018
- onOpenChange?.(false);
3019
- }, [onCancel, onOpenChange]);
3020
- const footer = useMemo(
3021
- () => /* @__PURE__ */ jsxs("div", { className: "flex gap-2 w-full", children: [
3022
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", className: "flex-1", onClick: handleCancel, children: cancelLabel }),
3023
- /* @__PURE__ */ jsx(
3024
- Button,
3025
- {
3026
- type: "button",
3027
- variant: confirmVariant,
3028
- className: "flex-1",
3029
- onClick: handleConfirm,
3030
- disabled: confirmDisabled || confirmLoading,
3031
- children: confirmLoading ? "Loading..." : confirmLabel
3032
- }
3033
- )
3034
- ] }),
3035
- [
3036
- cancelLabel,
3037
- confirmLabel,
3038
- confirmVariant,
3039
- confirmDisabled,
3040
- confirmLoading,
3041
- handleConfirm,
3042
- handleCancel
3043
- ]
3044
- );
3045
- return /* @__PURE__ */ jsx(
3046
- SheetWrapper,
3047
- {
3048
- open,
3049
- onOpenChange,
3050
- title,
3051
- description,
3052
- size,
3053
- footer,
3054
- ...props,
3055
- children
3056
- }
3057
- );
3058
- });
3059
3578
  function TableWrapper({
3060
3579
  title,
3061
3580
  description,
@@ -3238,12 +3757,6 @@ function FormInput({
3238
3757
  labelClassName,
3239
3758
  inputClassName,
3240
3759
  inputGroupClassName,
3241
- // PascalCase variants
3242
- IconLeft,
3243
- IconRight,
3244
- AddonLeft,
3245
- AddonRight,
3246
- // camelCase variants
3247
3760
  iconLeft,
3248
3761
  iconRight,
3249
3762
  addonLeft,
@@ -3263,10 +3776,6 @@ function FormInput({
3263
3776
  inputMode,
3264
3777
  enterKeyHint
3265
3778
  }) {
3266
- const resolvedIconLeft = IconLeft || iconLeft;
3267
- const resolvedIconRight = IconRight || iconRight;
3268
- const resolvedAddonLeft = AddonLeft || addonLeft;
3269
- const resolvedAddonRight = AddonRight || addonRight;
3270
3779
  const descriptionText = description || helperText;
3271
3780
  const handleChange = (e, field) => {
3272
3781
  const newValue = transform?.output ? transform.output(e.target.value) : e.target.value;
@@ -3277,7 +3786,7 @@ function FormInput({
3277
3786
  }
3278
3787
  onValueChange?.(newValue);
3279
3788
  };
3280
- const hasInputGroup = resolvedIconLeft || resolvedIconRight || resolvedAddonLeft || resolvedAddonRight;
3789
+ const hasInputGroup = iconLeft || iconRight || addonLeft || addonRight;
3281
3790
  const renderInput = (field, isDisabled, fieldState) => {
3282
3791
  const rawValue = field ? transform?.input ? transform.input(field.value) : field.value : transform?.input ? transform.input(value) : value;
3283
3792
  const safeValue = rawValue ?? "";
@@ -3313,9 +3822,9 @@ function FormInput({
3313
3822
  className: cn(inputGroupClassName),
3314
3823
  "data-disabled": isDisabled,
3315
3824
  children: [
3316
- (resolvedAddonLeft || resolvedIconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: resolvedAddonLeft || resolvedIconLeft }),
3825
+ (addonLeft || iconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: addonLeft || iconLeft }),
3317
3826
  /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps, className: inputClassName }),
3318
- (resolvedAddonRight || resolvedIconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: resolvedAddonRight || resolvedIconRight })
3827
+ (addonRight || iconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: addonRight || iconRight })
3319
3828
  ]
3320
3829
  }
3321
3830
  );
@@ -3374,12 +3883,6 @@ function FormTextarea({
3374
3883
  labelClassName,
3375
3884
  textareaClassName,
3376
3885
  inputGroupClassName,
3377
- // PascalCase variants
3378
- IconLeft,
3379
- IconRight,
3380
- AddonLeft,
3381
- AddonRight,
3382
- // camelCase variants
3383
3886
  iconLeft,
3384
3887
  iconRight,
3385
3888
  addonLeft,
@@ -3390,12 +3893,8 @@ function FormTextarea({
3390
3893
  autoComplete,
3391
3894
  autoFocus
3392
3895
  }) {
3393
- const resolvedIconLeft = IconLeft || iconLeft;
3394
- const resolvedIconRight = IconRight || iconRight;
3395
- const resolvedAddonLeft = AddonLeft || addonLeft;
3396
- const resolvedAddonRight = AddonRight || addonRight;
3397
3896
  const descriptionText = description || helperText;
3398
- const hasInputGroup = resolvedIconLeft || resolvedIconRight || resolvedAddonLeft || resolvedAddonRight;
3897
+ const hasInputGroup = iconLeft || iconRight || addonLeft || addonRight;
3399
3898
  const [localValue, setLocalValue] = useState(propValue || "");
3400
3899
  useEffect(() => {
3401
3900
  if (propValue !== void 0) {
@@ -3444,7 +3943,7 @@ function FormTextarea({
3444
3943
  className: cn(inputGroupClassName),
3445
3944
  "data-disabled": isDisabled,
3446
3945
  children: [
3447
- (resolvedAddonLeft || resolvedIconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: resolvedAddonLeft || resolvedIconLeft }),
3946
+ (addonLeft || iconLeft) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: addonLeft || iconLeft }),
3448
3947
  /* @__PURE__ */ jsx(
3449
3948
  InputGroupTextarea,
3450
3949
  {
@@ -3452,7 +3951,7 @@ function FormTextarea({
3452
3951
  className: cn("overflow-auto resize-none", textareaClassName)
3453
3952
  }
3454
3953
  ),
3455
- (resolvedAddonRight || resolvedIconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: resolvedAddonRight || resolvedIconRight })
3954
+ (addonRight || iconRight) && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: addonRight || iconRight })
3456
3955
  ]
3457
3956
  }
3458
3957
  );
@@ -3517,7 +4016,7 @@ function SelectInput({
3517
4016
  triggerClassName,
3518
4017
  contentClassName,
3519
4018
  itemClassName,
3520
- Icon: Icon2,
4019
+ Icon,
3521
4020
  onValueChange,
3522
4021
  value: propValue,
3523
4022
  defaultOpen,
@@ -3528,24 +4027,34 @@ function SelectInput({
3528
4027
  }) {
3529
4028
  const descriptionText = description || helperText;
3530
4029
  const CLEAR_VALUE = "__CLEAR__";
3531
- const filteredItems = items.filter((item) => {
3532
- const val = item.value;
3533
- return val !== void 0 && val !== null;
3534
- });
3535
- const displayItems = allOption ? [allOption, ...filteredItems] : filteredItems;
3536
- const filteredGroups = groups.map((group) => ({
3537
- ...group,
3538
- items: group.items.filter((item) => {
3539
- const val = item.value;
3540
- return val !== void 0 && val !== null;
3541
- })
3542
- })).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]);
3543
4040
  const [localValue, setLocalValue] = useState(propValue?.toString() || "");
3544
4041
  useEffect(() => {
3545
4042
  if (propValue !== void 0) {
3546
4043
  setLocalValue(propValue.toString());
3547
4044
  }
3548
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]);
3549
4058
  const renderSelect = (field, isDisabled, fieldState) => {
3550
4059
  const rawValue = field ? field.value?.toString() : localValue;
3551
4060
  const handleChange = (newValue) => {
@@ -3614,25 +4123,10 @@ function SelectInput({
3614
4123
  });
3615
4124
  };
3616
4125
  const selectValue = rawValue === "" ? CLEAR_VALUE : rawValue ? rawValue : void 0;
3617
- const findSelectedLabel = () => {
4126
+ const selectedLabel = (() => {
3618
4127
  if (!rawValue && rawValue !== "") return void 0;
3619
- for (const item of displayItems) {
3620
- const itemVal = item.value?.toString() ?? "";
3621
- if (itemVal === rawValue || itemVal === "" && rawValue === "") {
3622
- return item.label;
3623
- }
3624
- }
3625
- for (const group of filteredGroups) {
3626
- for (const item of group.items) {
3627
- const itemVal = item.value?.toString() ?? "";
3628
- if (itemVal === rawValue) {
3629
- return item.label;
3630
- }
3631
- }
3632
- }
3633
- return void 0;
3634
- };
3635
- const selectedLabel = findSelectedLabel();
4128
+ return labelMap.get(rawValue ?? "");
4129
+ })();
3636
4130
  return /* @__PURE__ */ jsxs(
3637
4131
  Select,
3638
4132
  {
@@ -3647,8 +4141,8 @@ function SelectInput({
3647
4141
  className: cn("w-full", triggerClassName),
3648
4142
  "aria-invalid": fieldState?.invalid || void 0,
3649
4143
  children: [
3650
- Icon2 && /* @__PURE__ */ jsx(Icon2, { className: "mr-2 h-4 w-4 text-primary" }),
3651
- /* @__PURE__ */ jsx(SelectValue, { placeholder, children: selectedLabel })
4144
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "mr-2 h-4 w-4 text-primary" }),
4145
+ /* @__PURE__ */ jsx(SelectValue, { placeholder, children: selectedLabel || null })
3652
4146
  ]
3653
4147
  }
3654
4148
  ),
@@ -4071,7 +4565,7 @@ function DateInput({
4071
4565
  onValueChange,
4072
4566
  value: propValue,
4073
4567
  onChange: propOnChange,
4074
- Icon: Icon2 = CalendarIcon,
4568
+ Icon = CalendarIcon,
4075
4569
  allowClear = true
4076
4570
  }) {
4077
4571
  const descriptionText = description || helperText;
@@ -4105,10 +4599,10 @@ function DateInput({
4105
4599
  year: "numeric"
4106
4600
  }) : placeholder;
4107
4601
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
4108
- /* @__PURE__ */ jsxs(
4602
+ /* @__PURE__ */ jsx(
4109
4603
  PopoverTrigger,
4110
4604
  {
4111
- render: /* @__PURE__ */ jsx(
4605
+ render: /* @__PURE__ */ jsxs(
4112
4606
  Button,
4113
4607
  {
4114
4608
  type: "button",
@@ -4118,20 +4612,20 @@ function DateInput({
4118
4612
  !selected && "text-muted-foreground",
4119
4613
  inputClassName
4120
4614
  ),
4121
- disabled: isDisabled
4615
+ disabled: isDisabled,
4616
+ children: [
4617
+ /* @__PURE__ */ jsx(Icon, { className: "mr-2 h-4 w-4" }),
4618
+ displayText,
4619
+ allowClear && selected && !isDisabled && /* @__PURE__ */ jsx(
4620
+ X,
4621
+ {
4622
+ className: "ml-auto h-4 w-4 opacity-50 hover:opacity-100",
4623
+ onClick: handleClear
4624
+ }
4625
+ )
4626
+ ]
4122
4627
  }
4123
- ),
4124
- children: [
4125
- /* @__PURE__ */ jsx(Icon2, { className: "mr-2 h-4 w-4" }),
4126
- displayText,
4127
- allowClear && selected && !isDisabled && /* @__PURE__ */ jsx(
4128
- X,
4129
- {
4130
- className: "ml-auto h-4 w-4 opacity-50 hover:opacity-100",
4131
- onClick: handleClear
4132
- }
4133
- )
4134
- ]
4628
+ )
4135
4629
  }
4136
4630
  ),
4137
4631
  /* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsx(
@@ -4609,10 +5103,10 @@ function TagChoiceInputInternal({
4609
5103
  }
4610
5104
  ),
4611
5105
  /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, modal: true, children: [
4612
- /* @__PURE__ */ jsxs(
5106
+ /* @__PURE__ */ jsx(
4613
5107
  PopoverTrigger,
4614
5108
  {
4615
- render: /* @__PURE__ */ jsx(
5109
+ render: /* @__PURE__ */ jsxs(
4616
5110
  Button,
4617
5111
  {
4618
5112
  type: "button",
@@ -4625,33 +5119,33 @@ function TagChoiceInputInternal({
4625
5119
  "hover:bg-accent/50 transition-colors",
4626
5120
  error && "border-destructive",
4627
5121
  disabled && "opacity-50 cursor-not-allowed"
4628
- )
4629
- }
4630
- ),
4631
- children: [
4632
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
4633
- /* @__PURE__ */ jsx(Tag, { className: "h-4 w-4 text-muted-foreground" }),
4634
- /* @__PURE__ */ jsx(
4635
- "span",
4636
- {
4637
- className: cn(
4638
- "text-sm",
4639
- selectedValues.length === 0 && "text-muted-foreground"
4640
- ),
4641
- children: selectedValues.length > 0 ? `${selectedValues.length} selected` : placeholder
4642
- }
4643
- )
4644
- ] }),
4645
- /* @__PURE__ */ jsx(
4646
- ChevronDown,
4647
- {
4648
- className: cn(
4649
- "h-4 w-4 text-muted-foreground transition-transform duration-200",
4650
- open && "rotate-180"
5122
+ ),
5123
+ children: [
5124
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
5125
+ /* @__PURE__ */ jsx(Tag, { className: "h-4 w-4 text-muted-foreground" }),
5126
+ /* @__PURE__ */ jsx(
5127
+ "span",
5128
+ {
5129
+ className: cn(
5130
+ "text-sm",
5131
+ selectedValues.length === 0 && "text-muted-foreground"
5132
+ ),
5133
+ children: selectedValues.length > 0 ? `${selectedValues.length} selected` : placeholder
5134
+ }
5135
+ )
5136
+ ] }),
5137
+ /* @__PURE__ */ jsx(
5138
+ ChevronDown,
5139
+ {
5140
+ className: cn(
5141
+ "h-4 w-4 text-muted-foreground transition-transform duration-200",
5142
+ open && "rotate-180"
5143
+ )
5144
+ }
4651
5145
  )
4652
- }
4653
- )
4654
- ]
5146
+ ]
5147
+ }
5148
+ )
4655
5149
  }
4656
5150
  ),
4657
5151
  /* @__PURE__ */ jsxs(
@@ -4719,7 +5213,7 @@ function TagChoiceInput({
4719
5213
  onValueChange
4720
5214
  }) {
4721
5215
  const descriptionText = description || helperText;
4722
- if (control && name) {
5216
+ if (control) {
4723
5217
  return /* @__PURE__ */ jsx(
4724
5218
  Controller,
4725
5219
  {
@@ -4762,15 +5256,11 @@ function TagChoiceInput({
4762
5256
  );
4763
5257
  }
4764
5258
  TagChoiceInput.displayName = "TagChoiceInput";
4765
- function generateStableKey(item, index, prefix) {
4766
- return `${prefix}-${item.value}-${index}`;
4767
- }
4768
5259
  function ComboboxInput({
4769
5260
  control,
4770
5261
  name,
4771
5262
  label,
4772
5263
  placeholder = "Select...",
4773
- searchPlaceholder = "Search...",
4774
5264
  emptyText = "No items found.",
4775
5265
  description,
4776
5266
  helperText,
@@ -4779,86 +5269,67 @@ function ComboboxInput({
4779
5269
  items = [],
4780
5270
  className,
4781
5271
  labelClassName,
4782
- triggerClassName,
5272
+ inputClassName,
4783
5273
  onValueChange,
4784
5274
  renderOption,
4785
5275
  value: propValue,
4786
5276
  onChange: propOnChange
4787
5277
  }) {
4788
5278
  const descriptionText = description || helperText;
4789
- const [open, setOpen] = useState(false);
4790
- const handleSelect = (selectedValue, field) => {
4791
- if (field) {
4792
- field.onChange(selectedValue);
4793
- } else if (propOnChange) {
4794
- propOnChange(selectedValue);
4795
- }
4796
- onValueChange?.(selectedValue);
4797
- setOpen(false);
4798
- };
5279
+ const itemValues = useMemo(() => items.map((item) => item.value), [items]);
5280
+ const handleValueChange = useCallback(
5281
+ (newValue, field) => {
5282
+ const safeValue = newValue || "";
5283
+ if (field) {
5284
+ field.onChange(safeValue);
5285
+ } else if (propOnChange) {
5286
+ propOnChange(safeValue);
5287
+ }
5288
+ onValueChange?.(safeValue);
5289
+ },
5290
+ [propOnChange, onValueChange]
5291
+ );
4799
5292
  const renderCombobox = (currentValue, field, isDisabled) => {
4800
- const selectedItem = items.find((item) => item.value === currentValue);
4801
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
4802
- /* @__PURE__ */ jsxs(
4803
- PopoverTrigger,
4804
- {
4805
- render: /* @__PURE__ */ jsx(
4806
- Button,
5293
+ return /* @__PURE__ */ jsxs(
5294
+ Combobox,
5295
+ {
5296
+ items: itemValues,
5297
+ value: currentValue,
5298
+ onValueChange: (value) => handleValueChange(value, field),
5299
+ disabled: isDisabled,
5300
+ children: [
5301
+ /* @__PURE__ */ jsx(
5302
+ ComboboxInput$1,
4807
5303
  {
4808
- variant: "outline",
4809
- role: "combobox",
4810
- "aria-expanded": open,
4811
- disabled: isDisabled,
4812
- className: cn(
4813
- "w-full justify-between font-normal",
4814
- !currentValue && "text-muted-foreground",
4815
- triggerClassName
4816
- )
5304
+ placeholder,
5305
+ className: cn(inputClassName)
4817
5306
  }
4818
5307
  ),
4819
- children: [
4820
- selectedItem ? selectedItem.label : placeholder,
4821
- /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
4822
- ]
4823
- }
4824
- ),
4825
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-(--anchor-width) p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
4826
- /* @__PURE__ */ jsx(CommandInput, { placeholder: searchPlaceholder }),
4827
- /* @__PURE__ */ jsxs(CommandList, { children: [
4828
- /* @__PURE__ */ jsx(CommandEmpty, { children: emptyText }),
4829
- /* @__PURE__ */ jsx(CommandGroup, { children: items.map((item, index) => {
4830
- const itemKey = generateStableKey(item, index, name || "combobox");
4831
- return /* @__PURE__ */ jsxs(
4832
- CommandItem,
4833
- {
4834
- value: item.label,
4835
- disabled: item.disabled,
4836
- onSelect: () => handleSelect(item.value, field),
4837
- children: [
4838
- renderOption ? renderOption(item) : item.label,
4839
- /* @__PURE__ */ jsx(
4840
- Check,
4841
- {
4842
- className: cn(
4843
- "ml-auto h-4 w-4",
4844
- currentValue === item.value ? "opacity-100" : "opacity-0"
4845
- )
4846
- }
4847
- )
4848
- ]
4849
- },
4850
- itemKey
4851
- );
4852
- }) })
4853
- ] })
4854
- ] }) })
4855
- ] });
5308
+ /* @__PURE__ */ jsxs(ComboboxContent, { children: [
5309
+ /* @__PURE__ */ jsx(ComboboxEmpty, { children: emptyText }),
5310
+ /* @__PURE__ */ jsx(ComboboxList, { children: (itemValue) => {
5311
+ const option = items.find((item) => item.value === itemValue);
5312
+ if (!option) return null;
5313
+ return /* @__PURE__ */ jsx(
5314
+ ComboboxItem,
5315
+ {
5316
+ value: option.value,
5317
+ disabled: option.disabled,
5318
+ children: renderOption ? renderOption(option) : option.label
5319
+ },
5320
+ option.value
5321
+ );
5322
+ } })
5323
+ ] })
5324
+ ]
5325
+ }
5326
+ );
4856
5327
  };
4857
5328
  if (!control) {
4858
5329
  return /* @__PURE__ */ jsxs(Field, { className, "data-disabled": disabled, children: [
4859
5330
  label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4860
5331
  label,
4861
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
5332
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
4862
5333
  ] }),
4863
5334
  renderCombobox(propValue, void 0, disabled),
4864
5335
  descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText })
@@ -4878,7 +5349,7 @@ function ComboboxInput({
4878
5349
  children: [
4879
5350
  label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4880
5351
  label,
4881
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
5352
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
4882
5353
  ] }),
4883
5354
  renderCombobox(field.value, field, disabled),
4884
5355
  descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
@@ -4893,110 +5364,108 @@ function generateSlug(text) {
4893
5364
  if (!text) return "";
4894
5365
  return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
4895
5366
  }
4896
- var SlugField = forwardRef(
4897
- ({
4898
- control,
4899
- name,
4900
- description,
4901
- helperText,
4902
- required,
4903
- label,
4904
- placeholder = "my-page-slug",
4905
- disabled,
4906
- sourceValue,
4907
- onGenerate,
4908
- className,
4909
- inputClassName,
4910
- labelClassName,
4911
- onValueChange,
4912
- value,
4913
- onChange,
4914
- error
4915
- }, ref) => {
4916
- const descriptionText = description || helperText;
4917
- const handleGenerate = (_currentValue, fieldOnChange) => {
4918
- const newSlug = onGenerate ? onGenerate(sourceValue || "") : generateSlug(sourceValue);
4919
- fieldOnChange?.(newSlug);
4920
- onValueChange?.(newSlug);
4921
- };
4922
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldState) => {
4923
- return /* @__PURE__ */ jsxs(InputGroup, { children: [
4924
- /* @__PURE__ */ jsx(
4925
- InputGroupInput,
4926
- {
4927
- ref,
4928
- id: name,
4929
- type: "text",
4930
- disabled: isDisabled,
4931
- placeholder,
4932
- value: fieldValue || "",
4933
- onChange: (e) => {
4934
- const newValue = e.target.value;
4935
- fieldOnChange?.(newValue);
4936
- onValueChange?.(newValue);
4937
- },
4938
- "aria-invalid": fieldState?.invalid,
4939
- className: inputClassName
4940
- }
4941
- ),
4942
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(
4943
- InputGroupButton,
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,
5397
+ {
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
5411
+ }
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
+ ) })
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,
4944
5437
  {
4945
- type: "button",
4946
- size: "sm",
4947
- onClick: () => handleGenerate(fieldValue, fieldOnChange),
4948
- disabled: isDisabled || !sourceValue,
4949
- title: "Generate slug from source",
5438
+ className,
5439
+ "data-disabled": disabled,
5440
+ "data-invalid": fieldState.invalid,
4950
5441
  children: [
4951
- /* @__PURE__ */ jsx(Wand2, { className: "h-4 w-4" }),
4952
- "Generate"
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] })
4953
5449
  ]
4954
5450
  }
4955
- ) })
4956
- ] });
4957
- };
4958
- if (control && name) {
4959
- return /* @__PURE__ */ jsx(
4960
- Controller,
4961
- {
4962
- name,
4963
- control,
4964
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(
4965
- Field,
4966
- {
4967
- className,
4968
- "data-disabled": disabled,
4969
- "data-invalid": fieldState.invalid,
4970
- children: [
4971
- label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4972
- label,
4973
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
4974
- ] }),
4975
- renderInput(field.value, field.onChange, disabled, fieldState),
4976
- descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
4977
- fieldState.invalid && fieldState.error && /* @__PURE__ */ jsx(FieldError, { errors: [fieldState.error] })
4978
- ]
4979
- }
4980
- )
4981
- }
4982
- );
4983
- }
4984
- const handleDirectChange = (newValue) => {
4985
- onChange?.({ target: { value: newValue } });
4986
- onValueChange?.(newValue);
4987
- };
4988
- return /* @__PURE__ */ jsxs(Field, { className, "data-disabled": disabled, children: [
4989
- label && /* @__PURE__ */ jsxs(FieldLabel, { htmlFor: name, className: labelClassName, children: [
4990
- label,
4991
- required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
4992
- ] }),
4993
- renderInput(value, handleDirectChange, disabled, { }),
4994
- descriptionText && /* @__PURE__ */ jsx(FieldDescription, { children: descriptionText }),
4995
- error && /* @__PURE__ */ jsx(FieldError, { errors: [error] })
4996
- ] });
5451
+ )
5452
+ }
5453
+ );
4997
5454
  }
4998
- );
4999
- 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
+ }
5000
5469
  var flattenErrors = (errors, prefix = "") => {
5001
5470
  const flattened = [];
5002
5471
  Object.entries(errors).forEach(([key, value]) => {
@@ -5058,12 +5527,12 @@ function DateRangeFilter({
5058
5527
  alignRight = true,
5059
5528
  numberOfMonths = 1
5060
5529
  }) {
5061
- const [dateRange, setDateRange] = React5.useState(
5530
+ const [dateRange, setDateRange] = React3.useState(
5062
5531
  initialStartDate || initialEndDate ? { from: initialStartDate, to: initialEndDate } : void 0
5063
5532
  );
5064
- const [appliedRange, setAppliedRange] = React5.useState(dateRange);
5065
- const [open, setOpen] = React5.useState(false);
5066
- React5.useEffect(() => {
5533
+ const [appliedRange, setAppliedRange] = React3.useState(dateRange);
5534
+ const [open, setOpen] = React3.useState(false);
5535
+ React3.useEffect(() => {
5067
5536
  const newRange = initialStartDate || initialEndDate ? { from: initialStartDate, to: initialEndDate } : void 0;
5068
5537
  setDateRange(newRange);
5069
5538
  setAppliedRange(newRange);
@@ -5096,32 +5565,32 @@ function DateRangeFilter({
5096
5565
  if (appliedRange.to) return `Until ${formatDate(appliedRange.to)}`;
5097
5566
  };
5098
5567
  return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
5099
- /* @__PURE__ */ jsxs(
5568
+ /* @__PURE__ */ jsx(
5100
5569
  PopoverTrigger,
5101
5570
  {
5102
- render: /* @__PURE__ */ jsx(
5571
+ render: /* @__PURE__ */ jsxs(
5103
5572
  Button,
5104
5573
  {
5105
5574
  type: "button",
5106
5575
  variant: "outline",
5107
5576
  className: cn(
5108
- "w-full justify-start text-left font-normal",
5577
+ "w-full justify-start font-normal",
5109
5578
  !(appliedRange?.from || appliedRange?.to) && "text-muted-foreground",
5110
5579
  buttonClassName
5111
- )
5580
+ ),
5581
+ children: [
5582
+ /* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 h-4 w-4" }),
5583
+ getDisplayText(),
5584
+ (appliedRange?.from || appliedRange?.to) && /* @__PURE__ */ jsx(
5585
+ X,
5586
+ {
5587
+ className: "ml-auto h-4 w-4 opacity-50 hover:opacity-100",
5588
+ onClick: handleClearFilter
5589
+ }
5590
+ )
5591
+ ]
5112
5592
  }
5113
- ),
5114
- children: [
5115
- /* @__PURE__ */ jsx(CalendarIcon, { className: "mr-2 h-4 w-4" }),
5116
- getDisplayText(),
5117
- (appliedRange?.from || appliedRange?.to) && /* @__PURE__ */ jsx(
5118
- X,
5119
- {
5120
- className: "ml-auto h-4 w-4 opacity-50 hover:opacity-100",
5121
- onClick: handleClearFilter
5122
- }
5123
- )
5124
- ]
5593
+ )
5125
5594
  }
5126
5595
  ),
5127
5596
  /* @__PURE__ */ jsx(
@@ -5182,7 +5651,7 @@ function DateRangePopover({
5182
5651
  calendarClassName,
5183
5652
  allowClear,
5184
5653
  showBadge,
5185
- Icon: Icon2,
5654
+ Icon,
5186
5655
  formatDateRange,
5187
5656
  isDateDisabled,
5188
5657
  handleDateRangeSelect,
@@ -5191,74 +5660,85 @@ function DateRangePopover({
5191
5660
  maxDate
5192
5661
  }) {
5193
5662
  const hasValue = dateRange?.from || dateRange?.to;
5194
- return /* @__PURE__ */ jsxs(Popover, { children: [
5195
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
5196
- /* @__PURE__ */ jsxs(
5197
- Button,
5663
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
5664
+ /* @__PURE__ */ jsxs(Popover, { children: [
5665
+ /* @__PURE__ */ jsx(
5666
+ PopoverTrigger,
5198
5667
  {
5199
- variant: hasValue ? "outline" : "secondary",
5200
- className: cn(
5201
- "w-full justify-start text-left font-normal",
5202
- !hasValue && "text-muted-foreground",
5203
- disabled && "cursor-not-allowed opacity-50",
5204
- hasValue && allowClear && "pr-8",
5205
- buttonClassName
5206
- ),
5207
- disabled,
5208
- type: "button",
5209
- children: [
5210
- /* @__PURE__ */ jsx(Icon2, { className: "mr-2 h-4 w-4" }),
5211
- hasValue ? /* @__PURE__ */ jsxs("span", { children: [
5212
- formatDateRange(dateRange),
5213
- showBadge && dateRange?.from && dateRange?.to && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs bg-secondary text-secondary-foreground py-0.5 px-2 rounded-full", children: formatDateRange(dateRange) })
5214
- ] }) : /* @__PURE__ */ jsx("span", { children: placeholder })
5215
- ]
5668
+ render: /* @__PURE__ */ jsxs(
5669
+ Button,
5670
+ {
5671
+ type: "button",
5672
+ disabled,
5673
+ variant: "outline",
5674
+ className: cn(
5675
+ "w-full justify-start gap-2 font-normal",
5676
+ !hasValue && "text-muted-foreground",
5677
+ hasValue && allowClear && "pr-10",
5678
+ buttonClassName
5679
+ ),
5680
+ children: [
5681
+ /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0" }),
5682
+ hasValue ? /* @__PURE__ */ jsxs("span", { className: "flex-1 truncate text-left", children: [
5683
+ formatDateRange(dateRange),
5684
+ showBadge && dateRange?.from && dateRange?.to && (() => {
5685
+ const from = dateRange.from instanceof Date ? dateRange.from : new Date(dateRange.from);
5686
+ const to = dateRange.to instanceof Date ? dateRange.to : new Date(dateRange.to);
5687
+ const days = Math.ceil((to.getTime() - from.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
5688
+ return /* @__PURE__ */ jsxs("span", { className: "ml-2 text-xs bg-secondary text-secondary-foreground py-0.5 px-2 rounded-full", children: [
5689
+ days,
5690
+ " ",
5691
+ days === 1 ? "day" : "days"
5692
+ ] });
5693
+ })()
5694
+ ] }) : /* @__PURE__ */ jsx("span", { className: "text-left", children: placeholder })
5695
+ ]
5696
+ }
5697
+ )
5216
5698
  }
5217
5699
  ),
5218
- hasValue && allowClear && !disabled && /* @__PURE__ */ jsxs(
5219
- Button,
5700
+ /* @__PURE__ */ jsxs(
5701
+ PopoverContent,
5220
5702
  {
5221
- type: "button",
5222
- variant: "ghost",
5223
- className: "absolute right-0 top-0 h-full px-2 hover:bg-transparent",
5224
- onClick: handleClear,
5703
+ className: cn("w-auto p-0", calendarClassName),
5704
+ align: "start",
5225
5705
  children: [
5226
- /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-muted-foreground hover:text-foreground" }),
5227
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Clear date range" })
5706
+ /* @__PURE__ */ jsx(
5707
+ Calendar,
5708
+ {
5709
+ mode: "range",
5710
+ selected: dateRange,
5711
+ onSelect: handleDateRangeSelect,
5712
+ disabled: isDateDisabled,
5713
+ initialFocus: true,
5714
+ ...minDate && { fromDate: minDate },
5715
+ ...maxDate && { toDate: maxDate }
5716
+ }
5717
+ ),
5718
+ /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", children: /* @__PURE__ */ jsx(
5719
+ Button,
5720
+ {
5721
+ variant: "ghost",
5722
+ size: "sm",
5723
+ onClick: handleClear,
5724
+ disabled: !hasValue,
5725
+ className: "w-full",
5726
+ type: "button",
5727
+ children: "Clear Date Range"
5728
+ }
5729
+ ) })
5228
5730
  ]
5229
5731
  }
5230
5732
  )
5231
- ] }) }),
5232
- /* @__PURE__ */ jsxs(
5233
- PopoverContent,
5733
+ ] }),
5734
+ hasValue && allowClear && !disabled && /* @__PURE__ */ jsx(
5735
+ "button",
5234
5736
  {
5235
- className: cn("w-auto p-0", calendarClassName),
5236
- align: "start",
5237
- children: [
5238
- /* @__PURE__ */ jsx(
5239
- Calendar,
5240
- {
5241
- mode: "range",
5242
- selected: dateRange,
5243
- onSelect: handleDateRangeSelect,
5244
- disabled: isDateDisabled,
5245
- initialFocus: true,
5246
- ...minDate && { fromDate: minDate },
5247
- ...maxDate && { toDate: maxDate }
5248
- }
5249
- ),
5250
- /* @__PURE__ */ jsx("div", { className: "p-3 border-t border-border", children: /* @__PURE__ */ jsx(
5251
- Button,
5252
- {
5253
- variant: "ghost",
5254
- size: "sm",
5255
- onClick: handleClear,
5256
- disabled: !hasValue,
5257
- className: "w-full",
5258
- children: "Clear Date Range"
5259
- }
5260
- ) })
5261
- ]
5737
+ type: "button",
5738
+ onClick: handleClear,
5739
+ className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded-sm hover:bg-muted transition-colors",
5740
+ "aria-label": "Clear date range",
5741
+ children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-muted-foreground hover:text-foreground" })
5262
5742
  }
5263
5743
  )
5264
5744
  ] });
@@ -5278,1426 +5758,170 @@ function DateRangeInput({
5278
5758
  name,
5279
5759
  label,
5280
5760
  description,
5281
- placeholder = "Select date range",
5282
- required,
5283
- disabled,
5284
- className,
5285
- labelClassName,
5286
- buttonClassName,
5287
- calendarClassName,
5288
- minDate,
5289
- maxDate,
5290
- disabledDates,
5291
- disabledDays,
5292
- onValueChange,
5293
- validateDateRange,
5294
- clearErrors,
5295
- descriptionComponent,
5296
- allowClear = true,
5297
- showBadge = true,
5298
- Icon: Icon2 = CalendarIcon,
5299
- transform = defaultTransform
5300
- }) {
5301
- const [localDateRange, setLocalDateRange] = useState({
5302
- from: void 0,
5303
- to: void 0
5304
- });
5305
- const formatDateRange = (range) => {
5306
- if (!range || !range.from && !range.to) return "";
5307
- const fromDate = range.from instanceof Date ? range.from : range.from ? new Date(range.from) : null;
5308
- const toDate2 = range.to instanceof Date ? range.to : range.to ? new Date(range.to) : null;
5309
- const fromFormatted = fromDate && isValid(fromDate) ? format(fromDate, "MMM d") : "";
5310
- const toFormatted = toDate2 && isValid(toDate2) ? format(toDate2, "MMM d") : "";
5311
- if (fromFormatted && toFormatted) {
5312
- return `${fromFormatted} - ${toFormatted}`;
5313
- } else if (fromFormatted) {
5314
- return `From ${fromFormatted}`;
5315
- } else if (toFormatted) {
5316
- return `Until ${toFormatted}`;
5317
- }
5318
- return "";
5319
- };
5320
- const isDateDisabled = (date) => {
5321
- if (!date || !isValid(date)) return true;
5322
- if (disabled) return true;
5323
- if (minDate && date < minDate) return true;
5324
- if (maxDate && date > maxDate) return true;
5325
- if (disabledDates?.some((d) => d.getTime() === date.getTime())) return true;
5326
- if (disabledDays?.includes(date.getDay())) return true;
5327
- return false;
5328
- };
5329
- const handleDateRangeSelect = (range, field) => {
5330
- if (disabled) return;
5331
- const safeRange = range || { from: void 0, to: void 0 };
5332
- if (validateDateRange && !validateDateRange(safeRange)) {
5333
- return;
5334
- }
5335
- if (field) {
5336
- const transformedValue = transform.output(safeRange);
5337
- field.onChange(transformedValue);
5338
- } else {
5339
- setLocalDateRange(safeRange);
5340
- }
5341
- onValueChange?.(safeRange);
5342
- if (clearErrors && name) {
5343
- clearErrors(name);
5344
- }
5345
- };
5346
- const handleClear = (field, e) => {
5347
- e.stopPropagation();
5348
- const emptyRange = { from: void 0, to: void 0 };
5349
- if (field) {
5350
- field.onChange(emptyRange);
5351
- } else {
5352
- setLocalDateRange(emptyRange);
5353
- }
5354
- onValueChange?.(emptyRange);
5355
- if (clearErrors && name) {
5356
- clearErrors(name);
5357
- }
5358
- };
5359
- if (control && name) {
5360
- return /* @__PURE__ */ jsx(
5361
- Controller,
5362
- {
5363
- control,
5364
- name,
5365
- render: ({ field, fieldState }) => {
5366
- const dateRange = transform.input(field.value);
5367
- return /* @__PURE__ */ jsxs(
5368
- Field,
5369
- {
5370
- className: cn("w-full", className),
5371
- "data-invalid": !!fieldState.error,
5372
- children: [
5373
- label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5374
- /* @__PURE__ */ jsxs(FieldLabel, { className: cn("grow", labelClassName), children: [
5375
- label,
5376
- required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5377
- ] }),
5378
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground shrink-0", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" }) })
5379
- ] }),
5380
- /* @__PURE__ */ jsx(
5381
- DateRangePopover,
5382
- {
5383
- dateRange,
5384
- placeholder,
5385
- disabled,
5386
- buttonClassName,
5387
- calendarClassName,
5388
- allowClear,
5389
- showBadge,
5390
- Icon: Icon2,
5391
- formatDateRange,
5392
- isDateDisabled,
5393
- handleDateRangeSelect: (range) => handleDateRangeSelect(range, field),
5394
- handleClear: (e) => handleClear(field, e),
5395
- minDate,
5396
- maxDate
5397
- }
5398
- ),
5399
- description && !descriptionComponent && /* @__PURE__ */ jsx(FieldDescription, { children: description }),
5400
- descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent }),
5401
- /* @__PURE__ */ jsx(
5402
- FieldError,
5403
- {
5404
- errors: fieldState.error ? [fieldState.error] : void 0
5405
- }
5406
- )
5407
- ]
5408
- }
5409
- );
5410
- }
5411
- }
5412
- );
5413
- }
5414
- return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
5415
- label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
5416
- /* @__PURE__ */ jsxs("div", { className: cn("text-sm font-medium flex-grow", labelClassName), children: [
5417
- label,
5418
- required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
5419
- ] }),
5420
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground flex-shrink-0", children: /* @__PURE__ */ jsx(Icon2, { className: "h-4 w-4" }) })
5421
- ] }),
5422
- /* @__PURE__ */ jsx(
5423
- DateRangePopover,
5424
- {
5425
- dateRange: localDateRange,
5426
- placeholder,
5427
- disabled,
5428
- buttonClassName,
5429
- calendarClassName,
5430
- allowClear,
5431
- showBadge,
5432
- Icon: Icon2,
5433
- formatDateRange,
5434
- isDateDisabled,
5435
- handleDateRangeSelect: (range) => handleDateRangeSelect(range),
5436
- handleClear: (e) => handleClear(null, e),
5437
- minDate,
5438
- maxDate
5439
- }
5440
- ),
5441
- description && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mt-1", children: description }),
5442
- descriptionComponent && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: descriptionComponent })
5443
- ] });
5444
- }
5445
-
5446
- // src/components/search/index.ts
5447
- var search_exports = {};
5448
- __export(search_exports, {
5449
- Actions: () => SearchActions,
5450
- Container: () => SearchContainer,
5451
- FilterActions: () => SearchFilterActions,
5452
- Filters: () => SearchFilters,
5453
- Input: () => SearchInput,
5454
- Root: () => SearchRoot,
5455
- SearchProvider: () => SearchProvider,
5456
- TypeInput: () => SearchTypeInput,
5457
- useSearch: () => useSearch
5458
- });
5459
- var SearchContext = createContext(void 0);
5460
- function SearchProvider({ children, value }) {
5461
- return /* @__PURE__ */ jsx(SearchContext.Provider, { value, children });
5462
- }
5463
- function useSearch() {
5464
- const context = useContext(SearchContext);
5465
- if (!context) {
5466
- throw new Error("useSearch must be used within SearchProvider");
5467
- }
5468
- return context;
5469
- }
5470
- function SearchRoot({ children, hook, className }) {
5471
- return /* @__PURE__ */ jsx(SearchProvider, { value: hook, children: /* @__PURE__ */ jsx("div", { className: cn("w-full", className), children }) });
5472
- }
5473
- function SearchInput({
5474
- placeholder = "Search...",
5475
- className,
5476
- disabled,
5477
- showIcon = true,
5478
- showClearButton = false,
5479
- onKeyDown,
5480
- ...props
5481
- }) {
5482
- const { searchValue, setSearchValue, handleSearch } = useSearch();
5483
- const handleKeyDown = (event) => {
5484
- onKeyDown?.(event);
5485
- if (!event.defaultPrevented && event.key === "Enter" && !disabled) {
5486
- handleSearch?.();
5487
- }
5488
- };
5489
- return /* @__PURE__ */ jsxs(
5490
- InputGroup,
5491
- {
5492
- className: cn("h-10 flex-1 shadow-sm", className),
5493
- "data-disabled": disabled || void 0,
5494
- children: [
5495
- showIcon && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(Search, { className: "size-4" }) }),
5496
- /* @__PURE__ */ jsx(
5497
- InputGroupInput,
5498
- {
5499
- ...props,
5500
- type: "text",
5501
- placeholder,
5502
- value: searchValue || "",
5503
- onChange: (e) => setSearchValue?.(e.target.value),
5504
- onKeyDown: handleKeyDown,
5505
- disabled,
5506
- className: "text-base"
5507
- }
5508
- ),
5509
- showClearButton && searchValue && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
5510
- InputGroupButton,
5511
- {
5512
- variant: "ghost",
5513
- size: "icon-sm",
5514
- onClick: () => setSearchValue?.(""),
5515
- disabled,
5516
- children: /* @__PURE__ */ jsx(X, { className: "size-4" })
5517
- }
5518
- ) })
5519
- ]
5520
- }
5521
- );
5522
- }
5523
- function SearchTypeInput({
5524
- placeholder = "Search...",
5525
- className,
5526
- disabled,
5527
- showIcon = true,
5528
- showClearButton = false,
5529
- searchTypeOptions = [],
5530
- onKeyDown,
5531
- ...props
5532
- }) {
5533
- const { searchValue, setSearchValue, searchType, setSearchType, handleSearch } = useSearch();
5534
- const handleKeyDown = (event) => {
5535
- onKeyDown?.(event);
5536
- if (!event.defaultPrevented && event.key === "Enter" && !disabled) {
5537
- handleSearch?.();
5538
- }
5539
- };
5540
- const selectedOption = searchTypeOptions.find((opt) => opt.value === searchType);
5541
- return /* @__PURE__ */ jsxs(
5542
- InputGroup,
5543
- {
5544
- className: cn("h-10 flex-1 shadow-sm", className),
5545
- "data-disabled": disabled || void 0,
5546
- children: [
5547
- showIcon && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(Search, { className: "size-4" }) }),
5548
- searchTypeOptions.length > 0 && /* @__PURE__ */ jsxs(InputGroupAddon, { align: "inline-start", className: "pr-0", children: [
5549
- /* @__PURE__ */ jsxs(
5550
- Select,
5551
- {
5552
- value: searchType,
5553
- onValueChange: setSearchType,
5554
- disabled,
5555
- children: [
5556
- /* @__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 }) }),
5557
- /* @__PURE__ */ jsx(SelectContent, { children: searchTypeOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
5558
- ]
5559
- }
5560
- ),
5561
- /* @__PURE__ */ jsx("div", { className: "h-6 w-px bg-border ml-1" })
5562
- ] }),
5563
- /* @__PURE__ */ jsx(
5564
- InputGroupInput,
5565
- {
5566
- ...props,
5567
- type: "text",
5568
- placeholder,
5569
- value: searchValue || "",
5570
- onChange: (e) => setSearchValue?.(e.target.value),
5571
- onKeyDown: handleKeyDown,
5572
- disabled,
5573
- className: "text-base"
5574
- }
5575
- ),
5576
- showClearButton && searchValue && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
5577
- InputGroupButton,
5578
- {
5579
- variant: "ghost",
5580
- size: "icon-sm",
5581
- onClick: () => setSearchValue?.(""),
5582
- disabled,
5583
- children: /* @__PURE__ */ jsx(X, { className: "size-4" })
5584
- }
5585
- ) })
5586
- ]
5587
- }
5588
- );
5589
- }
5590
- function SearchFilterActions({ onClose, disabled }) {
5591
- const { handleSearch, clearSearch, hasActiveFilters } = useSearch();
5592
- const handleApply = () => {
5593
- handleSearch?.();
5594
- onClose?.();
5595
- };
5596
- return /* @__PURE__ */ jsxs("div", { className: "flex gap-2 border-t bg-muted/30 p-4 pt-3 -mx-4 -mb-4", children: [
5597
- /* @__PURE__ */ jsx(
5598
- Button,
5599
- {
5600
- variant: "outline",
5601
- size: "sm",
5602
- onClick: clearSearch,
5603
- className: "flex-1",
5604
- disabled: disabled || !hasActiveFilters,
5605
- children: "Reset"
5606
- }
5607
- ),
5608
- /* @__PURE__ */ jsxs(Button, { size: "sm", onClick: handleApply, className: "flex-1", disabled, children: [
5609
- /* @__PURE__ */ jsx(Search, { size: 16, className: "mr-2" }),
5610
- "Apply"
5611
- ] })
5612
- ] });
5613
- }
5614
- function SearchFilters({
5615
- children,
5616
- title = "Filters",
5617
- description = "Refine your search results",
5618
- disabled,
5619
- className
5620
- }) {
5621
- const { hasActiveFilters, filters = {} } = useSearch();
5622
- const isMobile = useIsMobile();
5623
- const [isOpen, setIsOpen] = useState(false);
5624
- const activeFilterCount = Object.values(filters).filter((value) => {
5625
- if (Array.isArray(value)) {
5626
- return value.filter(Boolean).length > 0;
5627
- }
5628
- if (typeof value === "string") {
5629
- return value.trim().length > 0 && value !== "all";
5630
- }
5631
- if (typeof value === "number") {
5632
- return value !== void 0 && value !== null && !Number.isNaN(value);
5633
- }
5634
- if (typeof value === "boolean") {
5635
- return value;
5636
- }
5637
- return Boolean(value);
5638
- }).length;
5639
- const FilterContent = () => /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
5640
- /* @__PURE__ */ jsx("div", { className: "space-y-4", children }),
5641
- /* @__PURE__ */ jsx(SearchFilterActions, { onClose: () => setIsOpen(false) })
5642
- ] });
5643
- const triggerButton = /* @__PURE__ */ jsxs(
5644
- Button,
5645
- {
5646
- variant: "outline",
5647
- size: "default",
5648
- className: cn(
5649
- "relative h-10 w-10 shrink-0 px-0 sm:w-auto sm:px-4",
5650
- hasActiveFilters && "bg-primary/10 border-primary hover:bg-primary/15"
5651
- ),
5652
- disabled,
5653
- "aria-label": "Open filters",
5654
- children: [
5655
- /* @__PURE__ */ jsx(Filter, { className: "size-4" }),
5656
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline ml-2", children: "Filters" }),
5657
- activeFilterCount > 0 && /* @__PURE__ */ jsx(
5658
- Badge,
5659
- {
5660
- variant: "secondary",
5661
- 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",
5662
- children: activeFilterCount
5663
- }
5664
- )
5665
- ]
5666
- }
5667
- );
5668
- if (isMobile) {
5669
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5670
- /* @__PURE__ */ jsxs(
5671
- Button,
5672
- {
5673
- variant: "outline",
5674
- size: "default",
5675
- className: cn(
5676
- "relative h-10 w-10 shrink-0 px-0",
5677
- hasActiveFilters && "bg-primary/10 border-primary hover:bg-primary/15"
5678
- ),
5679
- disabled,
5680
- "aria-label": "Open filters",
5681
- onClick: () => setIsOpen(true),
5682
- children: [
5683
- /* @__PURE__ */ jsx(Filter, { className: "size-4" }),
5684
- activeFilterCount > 0 && /* @__PURE__ */ jsx(
5685
- Badge,
5686
- {
5687
- variant: "secondary",
5688
- 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",
5689
- children: activeFilterCount
5690
- }
5691
- )
5692
- ]
5693
- }
5694
- ),
5695
- /* @__PURE__ */ jsx(
5696
- SheetWrapper,
5697
- {
5698
- open: isOpen,
5699
- onOpenChange: setIsOpen,
5700
- title,
5701
- description,
5702
- side: "bottom",
5703
- size: "default",
5704
- children: /* @__PURE__ */ jsx(FilterContent, {})
5705
- }
5706
- )
5707
- ] });
5708
- }
5709
- return /* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
5710
- /* @__PURE__ */ jsx(PopoverTrigger, { render: triggerButton }),
5711
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-80 p-4 sm:w-96", align: "end", sideOffset: 8, children: /* @__PURE__ */ jsx(FilterContent, {}) })
5712
- ] });
5713
- }
5714
- function SearchActions({
5715
- showSearchButton = true,
5716
- showClearButton = true,
5717
- searchButtonText,
5718
- clearButtonText = "Clear",
5719
- disabled,
5720
- className
5721
- }) {
5722
- const { handleSearch, clearSearch, searchValue, hasActiveFilters, hasActiveSearch } = useSearch();
5723
- const isMobile = useIsMobile();
5724
- const canSearch = Boolean(searchValue?.trim() || hasActiveFilters);
5725
- const canClear = Boolean(searchValue?.trim() || hasActiveFilters || hasActiveSearch);
5726
- return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
5727
- showClearButton && canClear && (isMobile ? /* @__PURE__ */ jsx(
5728
- Button,
5729
- {
5730
- variant: "outline",
5731
- size: "icon",
5732
- onClick: clearSearch,
5733
- "aria-label": clearButtonText,
5734
- title: clearButtonText,
5735
- className: "shrink-0",
5736
- children: /* @__PURE__ */ jsx(RotateCcw, {})
5737
- }
5738
- ) : /* @__PURE__ */ jsx(
5739
- Button,
5740
- {
5741
- variant: "outline",
5742
- size: "default",
5743
- onClick: clearSearch,
5744
- className: "h-10 shrink-0",
5745
- children: clearButtonText
5746
- }
5747
- )),
5748
- showSearchButton && /* @__PURE__ */ jsxs(
5749
- Button,
5750
- {
5751
- size: "default",
5752
- onClick: handleSearch,
5753
- disabled: disabled || !canSearch,
5754
- className: "h-10 shrink-0 px-3 sm:px-4",
5755
- children: [
5756
- /* @__PURE__ */ jsx(
5757
- Search,
5758
- {
5759
- size: 16,
5760
- className: cn(searchButtonText ? "mr-2" : "sm:mr-2")
5761
- }
5762
- ),
5763
- /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: searchButtonText || "Search" })
5764
- ]
5765
- }
5766
- )
5767
- ] });
5768
- }
5769
- function SearchContainer({ children, className }) {
5770
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2 flex-1", className), children });
5771
- }
5772
- var FieldContext = createContext(null);
5773
- var Root = memo(function FieldRoot({
5774
- children,
5775
- className,
5776
- disabled = false,
5777
- invalid = false
5778
- }) {
5779
- const id = useId();
5780
- const value = useMemo(() => ({
5781
- id,
5782
- disabled,
5783
- invalid
5784
- }), [id, disabled, invalid]);
5785
- return /* @__PURE__ */ jsx(FieldContext.Provider, { value, children: /* @__PURE__ */ jsx("div", { className: cn("w-full", className), children }) });
5786
- });
5787
- var Label = memo(function FieldLabel13({ children, className }) {
5788
- const ctx = useContext(FieldContext);
5789
- return /* @__PURE__ */ jsx(
5790
- "label",
5791
- {
5792
- htmlFor: ctx?.id,
5793
- className: cn(
5794
- "absolute left-3 top-0 -translate-y-1/2 bg-background px-2",
5795
- "text-xs font-medium text-muted-foreground z-10",
5796
- "group-focus-within:text-primary whitespace-nowrap",
5797
- ctx?.disabled && "opacity-60",
5798
- ctx?.invalid && "text-destructive",
5799
- className
5800
- ),
5801
- children
5802
- }
5803
- );
5804
- });
5805
- var Error2 = memo(function FieldError13({ children, className }) {
5806
- if (!children) return null;
5807
- return /* @__PURE__ */ jsx("p", { className: cn("text-xs text-destructive mt-1.5", className), children });
5808
- });
5809
- var Icon = memo(function FieldIcon({ children, className }) {
5810
- return /* @__PURE__ */ jsx("div", { className: cn(
5811
- "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none z-10",
5812
- "text-muted-foreground",
5813
- className
5814
- ), children });
5815
- });
5816
- var Field13 = {
5817
- Root,
5818
- Label,
5819
- Error: Error2,
5820
- Icon
5821
- };
5822
- var CompactInput = forwardRef(({
5823
- // Form integration
5824
- control,
5825
- name,
5826
- description,
5827
- required,
5828
- // Basic props
5829
- label,
5830
- placeholder,
5831
- disabled,
5832
- type = "text",
5833
- // InputGroup addons
5834
- AddonLeft,
5835
- AddonRight,
5836
- // Styling
5837
- className,
5838
- inputClassName,
5839
- // Events
5840
- onValueChange,
5841
- // Direct usage
5842
- value,
5843
- onChange,
5844
- error,
5845
- // Valid HTML input attributes
5846
- autoComplete,
5847
- autoFocus,
5848
- maxLength,
5849
- minLength,
5850
- max,
5851
- min,
5852
- pattern,
5853
- readOnly,
5854
- step,
5855
- inputMode,
5856
- enterKeyHint,
5857
- ...props
5858
- }, ref) => {
5859
- const hasInputGroup = AddonLeft || AddonRight;
5860
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldError) => {
5861
- const inputProps = {
5862
- ref,
5863
- id: name,
5864
- name,
5865
- type,
5866
- disabled: isDisabled,
5867
- placeholder,
5868
- value: fieldValue || "",
5869
- onChange: (e) => {
5870
- const newValue = e.target.value;
5871
- fieldOnChange?.(newValue);
5872
- onValueChange?.(newValue);
5873
- },
5874
- className: cn(
5875
- "h-11",
5876
- fieldError && "border-destructive focus-visible:ring-destructive/20",
5877
- inputClassName
5878
- ),
5879
- autoComplete,
5880
- autoFocus,
5881
- maxLength,
5882
- minLength,
5883
- max,
5884
- min,
5885
- pattern,
5886
- readOnly,
5887
- step,
5888
- inputMode,
5889
- enterKeyHint,
5890
- ...props
5891
- };
5892
- if (hasInputGroup) {
5893
- return /* @__PURE__ */ jsxs(InputGroup, { children: [
5894
- AddonLeft && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: AddonLeft }),
5895
- /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps }),
5896
- AddonRight && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: AddonRight })
5897
- ] });
5898
- }
5899
- return /* @__PURE__ */ jsx(Input, { ...inputProps });
5900
- };
5901
- if (control && name) {
5902
- return /* @__PURE__ */ jsx(
5903
- Controller,
5904
- {
5905
- name,
5906
- control,
5907
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
5908
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
5909
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
5910
- renderInput(field.value, field.onChange, disabled, fieldState?.error?.message)
5911
- ] }),
5912
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
5913
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
5914
- ] })
5915
- }
5916
- );
5917
- }
5918
- const handleDirectChange = (newValue) => {
5919
- onChange?.({ target: { value: newValue } });
5920
- onValueChange?.(newValue);
5921
- };
5922
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
5923
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
5924
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
5925
- renderInput(value, handleDirectChange, disabled, error)
5926
- ] }),
5927
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
5928
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
5929
- ] });
5930
- });
5931
- CompactInput.displayName = "CompactInput";
5932
- var CompactTextarea = forwardRef(({
5933
- // Form integration
5934
- control,
5935
- name,
5936
- description,
5937
- required,
5938
- // Basic props
5939
- label,
5940
- placeholder,
5941
- disabled,
5942
- rows = 3,
5943
- // InputGroup addons
5944
- AddonLeft,
5945
- AddonRight,
5946
- // Styling
5947
- className,
5948
- inputClassName,
5949
- // Events
5950
- onValueChange,
5951
- // Direct usage
5952
- value,
5953
- onChange,
5954
- error,
5955
- // Valid HTML textarea attributes
5956
- cols,
5957
- wrap,
5958
- autoComplete,
5959
- autoFocus,
5960
- maxLength,
5961
- minLength,
5962
- readOnly,
5963
- spellCheck,
5964
- ...props
5965
- }, ref) => {
5966
- const hasInputGroup = AddonLeft || AddonRight;
5967
- const renderTextarea = (fieldValue, fieldOnChange, isDisabled, fieldError) => {
5968
- const currentCharCount = fieldValue?.length || 0;
5969
- const textareaProps = {
5970
- ref,
5971
- id: name,
5972
- name,
5973
- disabled: isDisabled,
5974
- placeholder,
5975
- rows,
5976
- value: fieldValue || "",
5977
- onChange: (e) => {
5978
- const newValue = e.target.value;
5979
- fieldOnChange?.(newValue);
5980
- onValueChange?.(newValue);
5981
- },
5982
- className: cn(
5983
- "resize-none pt-3",
5984
- fieldError && "border-destructive focus-visible:ring-destructive/20",
5985
- inputClassName
5986
- ),
5987
- cols,
5988
- wrap,
5989
- autoComplete,
5990
- autoFocus,
5991
- maxLength,
5992
- minLength,
5993
- readOnly,
5994
- spellCheck,
5995
- ...props
5996
- };
5997
- if (hasInputGroup) {
5998
- return /* @__PURE__ */ jsxs(Fragment, { children: [
5999
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6000
- AddonLeft && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-start", children: AddonLeft }),
6001
- /* @__PURE__ */ jsx(InputGroupTextarea, { ...textareaProps }),
6002
- AddonRight && /* @__PURE__ */ jsx(InputGroupAddon, { align: "block-end", children: AddonRight })
6003
- ] }),
6004
- maxLength && currentCharCount > 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1.5 text-right", children: [
6005
- currentCharCount,
6006
- "/",
6007
- maxLength
6008
- ] })
6009
- ] });
6010
- }
6011
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6012
- /* @__PURE__ */ jsx(Textarea, { ...textareaProps }),
6013
- maxLength && currentCharCount > 0 && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1.5 text-right", children: [
6014
- currentCharCount,
6015
- "/",
6016
- maxLength
6017
- ] })
6018
- ] });
6019
- };
6020
- if (control && name) {
6021
- return /* @__PURE__ */ jsx(
6022
- Controller,
6023
- {
6024
- name,
6025
- control,
6026
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
6027
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6028
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6029
- renderTextarea(field.value, field.onChange, disabled, fieldState?.error?.message)
6030
- ] }),
6031
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6032
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6033
- ] })
6034
- }
6035
- );
6036
- }
6037
- const handleDirectChange = (newValue) => {
6038
- onChange?.({ target: { value: newValue } });
6039
- onValueChange?.(newValue);
6040
- };
6041
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
6042
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6043
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6044
- renderTextarea(value, handleDirectChange, disabled, error)
6045
- ] }),
6046
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
6047
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6048
- ] });
6049
- });
6050
- CompactTextarea.displayName = "CompactTextarea";
6051
- var CompactSelect = forwardRef(({
6052
- // Form integration
6053
- control,
6054
- name,
6055
- description,
6056
- required,
6057
- // Basic props
6058
- label,
6059
- placeholder = "Select option",
6060
- disabled,
6061
- items = [],
6062
- // Styling
6063
- className,
6064
- // Events
6065
- onValueChange,
6066
- // Direct usage
6067
- value,
6068
- error,
6069
- ...props
6070
- }, ref) => {
6071
- if (control && name) {
6072
- return /* @__PURE__ */ jsx(
6073
- Controller,
6074
- {
6075
- name,
6076
- control,
6077
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { disabled, invalid: !!fieldState?.error, children: [
6078
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6079
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6080
- /* @__PURE__ */ jsxs(
6081
- Select,
6082
- {
6083
- value: field.value,
6084
- onValueChange: (val) => {
6085
- field.onChange(val);
6086
- onValueChange?.(val);
6087
- },
6088
- disabled,
6089
- ...props,
6090
- children: [
6091
- /* @__PURE__ */ jsx(
6092
- SelectTrigger,
6093
- {
6094
- ref,
6095
- id: name,
6096
- className: cn(
6097
- "h-11",
6098
- fieldState?.error && "border-destructive focus:ring-destructive/20",
6099
- className
6100
- ),
6101
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
6102
- }
6103
- ),
6104
- /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
6105
- ]
6106
- }
6107
- )
6108
- ] }),
6109
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6110
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6111
- ] })
6112
- }
6113
- );
6114
- }
6115
- return /* @__PURE__ */ jsxs(Field13.Root, { disabled, invalid: !!error, children: [
6116
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6117
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6118
- /* @__PURE__ */ jsxs(
6119
- Select,
6120
- {
6121
- value,
6122
- onValueChange,
6123
- disabled,
6124
- ...props,
6125
- children: [
6126
- /* @__PURE__ */ jsx(
6127
- SelectTrigger,
6128
- {
6129
- ref,
6130
- className: cn(
6131
- "h-11",
6132
- error && "border-destructive focus:ring-destructive/20",
6133
- className
6134
- ),
6135
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder })
6136
- }
6137
- ),
6138
- /* @__PURE__ */ jsx(SelectContent, { children: items.map((item) => /* @__PURE__ */ jsx(SelectItem, { value: item.value, children: item.label }, item.value)) })
6139
- ]
6140
- }
6141
- )
6142
- ] }),
6143
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6144
- ] });
6145
- });
6146
- CompactSelect.displayName = "CompactSelect";
6147
- var CompactNumberInput = forwardRef(({
6148
- // Form integration
6149
- control,
6150
- name,
6151
- description,
6152
- required,
6153
- // Basic props
6154
- label,
6155
- placeholder,
6156
- disabled,
6157
- // Number configuration
6158
- min = 0,
6159
- max,
6160
- step = 1,
6161
- // Display options
6162
- prefix,
6163
- suffix,
6164
- showButtons = false,
6165
- buttonVariant = "ghost",
6166
- // Styling
6167
- className,
6168
- inputClassName,
6169
- labelClassName,
6170
- containerClassName,
6171
- // Events
6172
- onValueChange,
6173
- // Direct usage
6174
- value,
6175
- defaultValue,
6176
- onChange,
6177
- error,
6178
- ...props
6179
- }, ref) => {
6180
- if (control && name) {
6181
- return /* @__PURE__ */ jsx(
6182
- Controller,
6183
- {
6184
- name,
6185
- control,
6186
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(
6187
- CompactNumberInputInternal,
6188
- {
6189
- ref,
6190
- label,
6191
- placeholder,
6192
- disabled,
6193
- min,
6194
- max,
6195
- step,
6196
- prefix,
6197
- suffix,
6198
- showButtons,
6199
- buttonVariant,
6200
- className,
6201
- inputClassName,
6202
- labelClassName,
6203
- containerClassName,
6204
- error: fieldState?.error?.message,
6205
- value: field.value ?? "",
6206
- onChange: (val) => {
6207
- field.onChange(val);
6208
- onValueChange?.(val);
6209
- },
6210
- ...props
6211
- }
6212
- )
6213
- }
6214
- );
6215
- }
6216
- return /* @__PURE__ */ jsx(
6217
- CompactNumberInputInternal,
6218
- {
6219
- ref,
6220
- label,
6221
- placeholder,
6222
- disabled,
6223
- min,
6224
- max,
6225
- step,
6226
- prefix,
6227
- suffix,
6228
- showButtons,
6229
- buttonVariant,
6230
- className,
6231
- inputClassName,
6232
- labelClassName,
6233
- containerClassName,
6234
- error,
6235
- value: value ?? "",
6236
- defaultValue,
6237
- onChange,
6238
- onValueChange,
6239
- ...props
6240
- }
6241
- );
6242
- });
6243
- var CompactNumberInputInternal = forwardRef(({
6244
- label,
6245
- placeholder,
6246
- min = 0,
6247
- max,
6248
- step = 1,
6249
- prefix,
6250
- suffix,
6251
- showButtons,
6252
- buttonVariant,
6253
- error,
6254
- className,
6255
- inputClassName,
6256
- labelClassName,
6257
- containerClassName,
6258
- disabled,
6259
- value,
6260
- defaultValue,
6261
- onChange,
6262
- onValueChange,
6263
- ...props
6264
- }, ref) => {
6265
- const handleIncrement = () => {
6266
- const currentValue = Number(value) || 0;
6267
- const newValue = currentValue + step;
6268
- if (max === void 0 || newValue <= max) {
6269
- const finalValue = Number(newValue.toFixed(10));
6270
- onChange?.(finalValue);
6271
- onValueChange?.(finalValue);
6272
- }
6273
- };
6274
- const handleDecrement = () => {
6275
- const currentValue = Number(value) || 0;
6276
- const newValue = currentValue - step;
6277
- if (newValue >= min) {
6278
- const finalValue = Number(newValue.toFixed(10));
6279
- onChange?.(finalValue);
6280
- onValueChange?.(finalValue);
6281
- }
6282
- };
6283
- const handleInputChange = (e) => {
6284
- const val = e.target.value;
6285
- if (val === "") {
6286
- onChange?.("");
6287
- onValueChange?.("");
6288
- return;
6289
- }
6290
- const numVal = Number(val);
6291
- if (!isNaN(numVal)) {
6292
- if (min !== void 0 && numVal < min || max !== void 0 && numVal > max) {
6293
- return;
6294
- }
6295
- onChange?.(numVal);
6296
- onValueChange?.(numVal);
6297
- }
6298
- };
6299
- if (showButtons) {
6300
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6301
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6302
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6303
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: /* @__PURE__ */ jsx(
6304
- InputGroupButton,
6305
- {
6306
- type: "button",
6307
- variant: buttonVariant,
6308
- size: "icon-sm",
6309
- onClick: handleDecrement,
6310
- disabled: disabled || Number(value) <= min,
6311
- children: /* @__PURE__ */ jsx(Minus, { className: "h-4 w-4" })
6312
- }
6313
- ) }),
6314
- /* @__PURE__ */ jsx(
6315
- InputGroupInput,
6316
- {
6317
- ref,
6318
- type: "number",
6319
- value,
6320
- defaultValue,
6321
- onChange: handleInputChange,
6322
- min,
6323
- max,
6324
- step,
6325
- disabled,
6326
- placeholder,
6327
- className: cn("text-center", inputClassName, className),
6328
- ...props
6329
- }
6330
- ),
6331
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsx(
6332
- InputGroupButton,
6333
- {
6334
- type: "button",
6335
- variant: buttonVariant,
6336
- size: "icon-sm",
6337
- onClick: handleIncrement,
6338
- disabled: disabled || max !== void 0 && Number(value) >= max,
6339
- children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
6340
- }
6341
- ) })
6342
- ] }),
6343
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6344
- ] });
6345
- }
6346
- if (prefix || suffix) {
6347
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6348
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6349
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6350
- prefix && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-start", children: typeof prefix === "string" ? /* @__PURE__ */ jsx("span", { className: "text-xs", children: prefix }) : prefix }),
6351
- /* @__PURE__ */ jsx(
6352
- InputGroupInput,
6353
- {
6354
- ref,
6355
- type: "number",
6356
- value,
6357
- defaultValue,
6358
- onChange: handleInputChange,
6359
- min,
6360
- max,
6361
- step,
6362
- disabled,
6363
- placeholder,
6364
- className: cn(inputClassName, className),
6365
- ...props
6366
- }
6367
- ),
6368
- suffix && /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: typeof suffix === "string" ? /* @__PURE__ */ jsx("span", { className: "text-xs", children: suffix }) : suffix })
6369
- ] }),
6370
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6371
- ] });
6372
- }
6373
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6374
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6375
- /* @__PURE__ */ jsx(
6376
- Input,
6377
- {
6378
- ref,
6379
- type: "number",
6380
- value,
6381
- defaultValue,
6382
- onChange: handleInputChange,
6383
- min,
6384
- max,
6385
- step,
6386
- disabled,
6387
- placeholder,
6388
- className: cn(
6389
- "h-11 transition-all duration-200",
6390
- error && "border-destructive focus-visible:ring-destructive/20",
6391
- inputClassName,
6392
- className
6393
- ),
6394
- ...props
6395
- }
6396
- ),
6397
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6398
- ] });
6399
- });
6400
- CompactNumberInput.displayName = "CompactNumberInput";
6401
- CompactNumberInputInternal.displayName = "CompactNumberInputInternal";
6402
- var CompactTagChoice = forwardRef(({
6403
- // Form integration
6404
- control,
6405
- name,
6406
- // Display
6407
- label,
6408
- description,
6409
- placeholder = "Select options...",
6410
- required,
6411
- disabled,
6412
- // Data
6413
- choices = [],
6414
- maxSelections,
6415
- // Styling
6416
- className,
6417
- containerClassName,
6418
- labelClassName,
6419
- inputClassName,
6420
- // Direct usage
6421
- value: propValue = [],
6422
- onChange: propOnChange,
6423
- onValueChange,
6424
- error
6425
- }, ref) => {
6426
- if (control && name) {
6427
- return /* @__PURE__ */ jsx(
6428
- Controller,
6429
- {
6430
- name,
6431
- control,
6432
- render: ({ field, fieldState }) => /* @__PURE__ */ jsx(
6433
- CompactTagChoiceInternal,
6434
- {
6435
- ref,
6436
- label,
6437
- placeholder,
6438
- disabled,
6439
- error: fieldState?.error?.message,
6440
- value: field.value || [],
6441
- onChange: (vals) => {
6442
- field.onChange(vals);
6443
- onValueChange?.(vals);
6444
- },
6445
- choices,
6446
- maxSelections,
6447
- containerClassName: cn(className, containerClassName),
6448
- labelClassName,
6449
- inputClassName
6450
- }
6451
- )
6452
- }
6453
- );
6454
- }
6455
- return /* @__PURE__ */ jsx(
6456
- CompactTagChoiceInternal,
6457
- {
6458
- ref,
6459
- label,
6460
- placeholder,
6461
- disabled,
6462
- value: propValue,
6463
- onChange: (vals) => {
6464
- propOnChange?.(vals);
6465
- onValueChange?.(vals);
6466
- },
6467
- choices,
6468
- maxSelections,
6469
- containerClassName,
6470
- labelClassName,
6471
- inputClassName,
6472
- className,
6473
- error
6474
- }
6475
- );
6476
- });
6477
- var CompactTagChoiceInternal = forwardRef(({
6478
- label,
6479
- placeholder,
6480
- disabled,
6481
- value = [],
6482
- onChange,
6483
- choices = [],
6484
- maxSelections,
6485
- error,
6486
- className,
6487
- containerClassName,
6488
- labelClassName,
6489
- inputClassName
6490
- }, ref) => {
6491
- const [open, setOpen] = useState(false);
6492
- const triggerRef = useRef(null);
6493
- const availableChoices = choices.filter((c) => !value.includes(c.value));
6494
- const addChoice = (choiceValue) => {
6495
- if (value.includes(choiceValue)) return;
6496
- if (maxSelections && value.length >= maxSelections) return;
6497
- const updated = [...value, choiceValue];
6498
- onChange?.(updated);
6499
- };
6500
- const removeChoice = (choiceValue) => {
6501
- const updated = value.filter((v) => v !== choiceValue);
6502
- onChange?.(updated);
6503
- };
6504
- return /* @__PURE__ */ jsxs(Field13.Root, { className: containerClassName, disabled, invalid: !!error, children: [
6505
- label && /* @__PURE__ */ jsx(Field13.Label, { className: labelClassName, children: label }),
6506
- /* @__PURE__ */ jsxs(
6507
- "div",
6508
- {
6509
- className: cn(
6510
- "min-h-[2.5rem] w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
6511
- "ring-offset-background focus-within:ring-1 focus-within:ring-primary/20",
6512
- "hover:border-primary/50 transition-all duration-200",
6513
- error && "border-destructive focus-within:ring-destructive/20",
6514
- disabled && "opacity-50 cursor-not-allowed",
6515
- inputClassName
6516
- ),
6517
- ref,
6518
- children: [
6519
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1 mb-2", children: value.map((val) => {
6520
- const choice = choices.find((c) => c.value === val);
6521
- return /* @__PURE__ */ jsxs(Badge, { variant: "secondary", className: "flex items-center gap-1 px-2 py-1", children: [
6522
- /* @__PURE__ */ jsx("span", { children: choice?.label ?? val }),
6523
- !disabled && /* @__PURE__ */ jsx(
6524
- Button,
6525
- {
6526
- type: "button",
6527
- variant: "ghost",
6528
- size: "sm",
6529
- className: "h-auto p-0 text-muted-foreground hover:text-foreground",
6530
- onClick: (e) => {
6531
- e.preventDefault();
6532
- e.stopPropagation();
6533
- removeChoice(val);
6534
- },
6535
- children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
6536
- }
6537
- )
6538
- ] }, val);
6539
- }) }),
6540
- !disabled && availableChoices.length > 0 && (!maxSelections || value.length < maxSelections) && /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
6541
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
6542
- Button,
6543
- {
6544
- ref: triggerRef,
6545
- type: "button",
6546
- variant: "ghost",
6547
- size: "sm",
6548
- className: "h-auto p-1 text-muted-foreground hover:text-foreground",
6549
- onClick: (e) => {
6550
- e.preventDefault();
6551
- e.stopPropagation();
6552
- setOpen(true);
6553
- },
6554
- children: [
6555
- /* @__PURE__ */ jsx(Plus, { className: "h-3 w-3 mr-1" }),
6556
- value.length === 0 ? placeholder : "Add more..."
6557
- ]
6558
- }
6559
- ) }),
6560
- /* @__PURE__ */ jsx(PopoverContent, { className: "w-[220px] p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "p-1", children: [
6561
- 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(
6562
- "div",
6563
- {
6564
- onClick: (e) => {
6565
- e.preventDefault();
6566
- e.stopPropagation();
6567
- addChoice(choice.value);
6568
- },
6569
- className: "flex items-center justify-between px-2 py-2 text-sm rounded-sm hover:bg-accent hover:text-accent-foreground cursor-pointer",
6570
- children: [
6571
- /* @__PURE__ */ jsx("span", { children: choice.label }),
6572
- value.includes(choice.value) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" })
6573
- ]
6574
- },
6575
- choice.value
6576
- )) }),
6577
- /* @__PURE__ */ jsx("div", { className: "border-t px-2 py-2 text-xs text-muted-foreground", children: "Click to select \u2022 Click outside to close" })
6578
- ] }) })
6579
- ] }),
6580
- maxSelections && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-1", children: [
6581
- value.length,
6582
- "/",
6583
- maxSelections,
6584
- " selected"
6585
- ] })
6586
- ]
6587
- }
6588
- ),
6589
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error })
6590
- ] });
6591
- });
6592
- CompactTagChoice.displayName = "CompactTagChoice";
6593
- CompactTagChoiceInternal.displayName = "CompactTagChoiceInternal";
6594
- function generateSlug2(text) {
6595
- if (!text) return "";
6596
- return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
6597
- }
6598
- var CompactSlugField = forwardRef(({
6599
- // Form integration
6600
- control,
6601
- name,
6602
- description,
5761
+ placeholder = "Select date range",
6603
5762
  required,
6604
- // Basic props
6605
- label,
6606
- placeholder = "my-page-slug",
6607
5763
  disabled,
6608
- // Icon support
6609
- icon,
6610
- // Slug generation
6611
- sourceValue,
6612
- onGenerate,
6613
- // Styling
6614
5764
  className,
6615
- inputClassName,
6616
- // Events
5765
+ labelClassName,
5766
+ buttonClassName,
5767
+ calendarClassName,
5768
+ minDate,
5769
+ maxDate,
5770
+ disabledDates,
5771
+ disabledDays,
6617
5772
  onValueChange,
6618
- // Direct usage
6619
- value,
6620
- onChange,
6621
- error,
6622
- ...props
6623
- }, ref) => {
6624
- const handleGenerate = (currentValue, fieldOnChange) => {
6625
- const newSlug = onGenerate ? onGenerate(sourceValue || "") : generateSlug2(sourceValue || "");
6626
- fieldOnChange(newSlug);
6627
- 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 "";
6628
5799
  };
6629
- const renderInput = (fieldValue, fieldOnChange, isDisabled, fieldState) => {
6630
- const inputProps = {
6631
- ref,
6632
- id: name,
6633
- type: "text",
6634
- disabled: isDisabled,
6635
- placeholder,
6636
- value: fieldValue || "",
6637
- onChange: (e) => {
6638
- const newValue = e.target.value;
6639
- fieldOnChange(newValue);
6640
- onValueChange?.(newValue);
6641
- },
6642
- className: cn(
6643
- "h-11",
6644
- fieldState?.error && "border-destructive focus-visible:ring-destructive/20",
6645
- inputClassName
6646
- ),
6647
- ...props
6648
- };
6649
- return /* @__PURE__ */ jsxs(Fragment, { children: [
6650
- icon && /* @__PURE__ */ jsx(Field13.Icon, { children: icon }),
6651
- /* @__PURE__ */ jsxs(InputGroup, { children: [
6652
- /* @__PURE__ */ jsx(InputGroupInput, { ...inputProps, className: cn(inputProps.className, icon && "pl-9") }),
6653
- /* @__PURE__ */ jsx(InputGroupAddon, { align: "inline-end", children: /* @__PURE__ */ jsxs(
6654
- InputGroupButton,
6655
- {
6656
- type: "button",
6657
- size: "sm",
6658
- onClick: () => handleGenerate(fieldValue, fieldOnChange),
6659
- disabled: isDisabled || !sourceValue,
6660
- title: "Generate slug from name",
6661
- children: [
6662
- /* @__PURE__ */ jsx(Wand2, { className: "h-4 w-4" }),
6663
- "Generate"
6664
- ]
6665
- }
6666
- ) })
6667
- ] })
6668
- ] });
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;
6669
5808
  };
6670
- 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) {
6671
5840
  return /* @__PURE__ */ jsx(
6672
5841
  Controller,
6673
5842
  {
6674
- name,
6675
5843
  control,
6676
- render: ({ field, fieldState }) => /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!fieldState?.error, children: [
6677
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6678
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6679
- renderInput(field.value, field.onChange, disabled, fieldState)
6680
- ] }),
6681
- fieldState?.error && /* @__PURE__ */ jsx(Field13.Error, { children: fieldState.error.message }),
6682
- description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1.5", children: description })
6683
- ] })
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
+ }
6684
5891
  }
6685
5892
  );
6686
5893
  }
6687
- const handleDirectChange = (newValue) => {
6688
- onChange?.({ target: { value: newValue } });
6689
- onValueChange?.(newValue);
6690
- };
6691
- return /* @__PURE__ */ jsxs(Field13.Root, { className, disabled, invalid: !!error, children: [
6692
- /* @__PURE__ */ jsxs("div", { className: "relative group", children: [
6693
- label && /* @__PURE__ */ jsx(Field13.Label, { children: label }),
6694
- 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" }) })
6695
5901
  ] }),
6696
- error && /* @__PURE__ */ jsx(Field13.Error, { children: error }),
6697
- 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 })
6698
5923
  ] });
6699
- });
6700
- CompactSlugField.displayName = "CompactSlugField";
5924
+ }
6701
5925
  var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
6702
5926
  function EventCalendar({
6703
5927
  events = [],
@@ -6962,7 +6186,275 @@ function CalendarWithDetail({
6962
6186
  }
6963
6187
  );
6964
6188
  }
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"
6197
+ };
6198
+ var SLIDE_MAP = {
6199
+ left: "slideInLeft",
6200
+ right: "slideInRight",
6201
+ up: "slideInUp",
6202
+ down: "slideInDown"
6203
+ };
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,
6247
+ children,
6248
+ delay = 0,
6249
+ duration = 600,
6250
+ inView = false,
6251
+ inViewMargin,
6252
+ once = true,
6253
+ disabled = false,
6254
+ className,
6255
+ as = "div"
6256
+ }) {
6257
+ const { ref, shouldAnimate, active } = useAnimationState({
6258
+ inView,
6259
+ inViewMargin,
6260
+ once,
6261
+ disabled
6262
+ });
6263
+ return createElement(
6264
+ as,
6265
+ {
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
6276
+ );
6277
+ }
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({
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,
6398
+ className,
6399
+ as = "span"
6400
+ }) {
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
+ );
6456
+ }
6965
6457
 
6966
- export { AccordionSection, ActionDropdown, ActionTooltip, ApiPagination, ButtonTooltip, CalendarDayDetail, CalendarWithDetail, CardWrapper, CheckboxDropdown, CheckboxInput, ClientSubmitButton, CollapsibleCard, CollapsibleSection, CollapsibleWrapper, ComboboxInput, CompactInput, CompactNumberInput, CompactSelect, CompactSlugField, CompactTagChoice, CompactTextarea, ConfirmDialog, ConfirmSheet, 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, 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 };
6967
6459
  //# sourceMappingURL=index.js.map
6968
6460
  //# sourceMappingURL=index.js.map