@schandlergarcia/sf-web-components 1.9.37 → 1.9.39

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.
Files changed (109) hide show
  1. package/package.json +4 -1
  2. package/scripts/postinstall.mjs +116 -65
  3. package/src/components/library/cards/ActionList.jsx +38 -0
  4. package/src/components/library/cards/ActivityCard.jsx +56 -0
  5. package/src/components/library/cards/BaseCard.jsx +109 -0
  6. package/src/components/library/cards/CalloutCard.jsx +37 -0
  7. package/src/components/library/cards/ChartCard.jsx +105 -0
  8. package/src/components/library/cards/FeedPanel.jsx +39 -0
  9. package/src/components/library/cards/ListCard.jsx +193 -0
  10. package/src/components/library/cards/MetricCard.jsx +109 -0
  11. package/src/components/library/cards/MetricsStrip.jsx +78 -0
  12. package/src/components/library/cards/SectionCard.jsx +83 -0
  13. package/src/components/library/cards/SemanticMetricCard.jsx +52 -0
  14. package/src/components/library/cards/SemanticMetricCardWithLoading.jsx +23 -0
  15. package/src/components/library/cards/SemanticTableCard.jsx +48 -0
  16. package/src/components/library/cards/SemanticTableCardWithLoading.jsx +22 -0
  17. package/src/components/library/cards/StatusCard.jsx +220 -0
  18. package/src/components/library/cards/TableCard.jsx +337 -0
  19. package/src/components/library/cards/WidgetCard.jsx +90 -0
  20. package/src/components/library/charts/D3Chart.jsx +109 -0
  21. package/src/components/library/charts/D3ChartTemplates.jsx +126 -0
  22. package/src/components/library/charts/GeoMap.jsx +293 -0
  23. package/src/components/library/chat/ChatBar.jsx +256 -0
  24. package/src/components/library/chat/ChatInput.jsx +89 -0
  25. package/src/components/library/chat/ChatMessage.jsx +178 -0
  26. package/src/components/library/chat/ChatMessageList.jsx +73 -0
  27. package/src/components/library/chat/ChatPanel.jsx +97 -0
  28. package/src/components/library/chat/ChatSuggestions.jsx +28 -0
  29. package/src/components/library/chat/ChatToolCall.jsx +100 -0
  30. package/src/components/library/chat/ChatTypingIndicator.jsx +23 -0
  31. package/src/components/library/chat/ChatWelcome.jsx +43 -0
  32. package/src/components/library/chat/index.jsx +10 -0
  33. package/src/components/library/chat/useChatState.jsx +130 -0
  34. package/src/components/library/data/DataModeProvider.jsx +67 -0
  35. package/src/components/library/data/DataModeToggle.jsx +36 -0
  36. package/src/components/library/data/chartDataProvider.jsx +61 -0
  37. package/src/components/library/data/filterUtils.jsx +141 -0
  38. package/src/components/library/data/useDataSource.jsx +33 -0
  39. package/src/components/library/data/usePageFilters.jsx +99 -0
  40. package/src/components/library/filters/FilterBar.jsx +95 -0
  41. package/src/components/library/filters/SearchFilter.jsx +36 -0
  42. package/src/components/library/filters/SelectFilter.jsx +55 -0
  43. package/src/components/library/filters/ToggleFilter.jsx +52 -0
  44. package/src/components/library/filters/index.jsx +4 -0
  45. package/src/components/library/forms/FormField.jsx +291 -0
  46. package/src/components/library/forms/FormModal.jsx +201 -0
  47. package/src/components/library/forms/FormRenderer.jsx +46 -0
  48. package/src/components/library/forms/FormSection.jsx +69 -0
  49. package/src/components/library/forms/index.jsx +5 -0
  50. package/src/components/library/forms/useFormState.jsx +165 -0
  51. package/src/components/library/heroui/Accordion.jsx +26 -0
  52. package/src/components/library/heroui/Alert.jsx +8 -0
  53. package/src/components/library/heroui/Badge.jsx +8 -0
  54. package/src/components/library/heroui/Breadcrumbs.jsx +22 -0
  55. package/src/components/library/heroui/Button.jsx +58 -0
  56. package/src/components/library/heroui/Card.jsx +8 -0
  57. package/src/components/library/heroui/Collapsible.jsx +42 -0
  58. package/src/components/library/heroui/DatePicker.jsx +34 -0
  59. package/src/components/library/heroui/Dialog.jsx +37 -0
  60. package/src/components/library/heroui/Drawer.jsx +32 -0
  61. package/src/components/library/heroui/Dropdown.jsx +28 -0
  62. package/src/components/library/heroui/Field.jsx +51 -0
  63. package/src/components/library/heroui/Input.jsx +6 -0
  64. package/src/components/library/heroui/Kbd.jsx +8 -0
  65. package/src/components/library/heroui/Meter.jsx +8 -0
  66. package/src/components/library/heroui/Modal.jsx +32 -0
  67. package/src/components/library/heroui/Pagination.jsx +8 -0
  68. package/src/components/library/heroui/Popover.jsx +64 -0
  69. package/src/components/library/heroui/ProgressBar.jsx +8 -0
  70. package/src/components/library/heroui/ProgressCircle.jsx +8 -0
  71. package/src/components/library/heroui/ScrollShadow.jsx +8 -0
  72. package/src/components/library/heroui/Select.jsx +37 -0
  73. package/src/components/library/heroui/Separator.jsx +8 -0
  74. package/src/components/library/heroui/Skeleton.jsx +8 -0
  75. package/src/components/library/heroui/Tabs.jsx +26 -0
  76. package/src/components/library/heroui/Toast.jsx +25 -0
  77. package/src/components/library/heroui/Toggle.jsx +14 -0
  78. package/src/components/library/heroui/Tooltip.jsx +21 -0
  79. package/src/components/library/index.jsx +146 -0
  80. package/src/components/library/layout/PageContainer.jsx +11 -0
  81. package/src/components/library/skeletons/CardSkeleton.jsx +30 -0
  82. package/src/components/library/theme/AppThemeProvider.jsx +67 -0
  83. package/src/components/library/theme/tokens.jsx +72 -0
  84. package/src/components/library/ui/Alert.jsx +80 -0
  85. package/src/components/library/ui/Avatar.jsx +44 -0
  86. package/src/components/library/ui/BreadcrumbExtras.tsx +120 -0
  87. package/src/components/library/ui/Button.jsx +61 -0
  88. package/src/components/library/ui/Card.jsx +117 -0
  89. package/src/components/library/ui/Checkbox.jsx +17 -0
  90. package/src/components/library/ui/Chip.jsx +38 -0
  91. package/src/components/library/ui/Collapsible.tsx +31 -0
  92. package/src/components/library/ui/Container.jsx +56 -0
  93. package/src/components/library/ui/DatePicker.tsx +34 -0
  94. package/src/components/library/ui/Dialog.tsx +141 -0
  95. package/src/components/library/ui/EmptyState.jsx +46 -0
  96. package/src/components/library/ui/Field.tsx +82 -0
  97. package/src/components/library/ui/FieldGroup.jsx +17 -0
  98. package/src/components/library/ui/Input.jsx +21 -0
  99. package/src/components/library/ui/Label.jsx +22 -0
  100. package/src/components/library/ui/PaginationExtras.tsx +142 -0
  101. package/src/components/library/ui/Popover.tsx +39 -0
  102. package/src/components/library/ui/Select.tsx +113 -0
  103. package/src/components/library/ui/Spinner.d.ts +10 -0
  104. package/src/components/library/ui/Spinner.jsx +64 -0
  105. package/src/components/library/ui/Text.jsx +46 -0
  106. package/src/components/library/ui/Toggle.jsx +42 -0
  107. package/src/components/workspace/ComponentRegistry.jsx +297 -0
  108. package/src/lib/index.ts +1 -0
  109. package/src/lib/utils.ts +6 -0
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import UIText from "./Text";
3
+
4
+ export default function UIContainer({
5
+ title,
6
+ subtitle,
7
+ description,
8
+ actions,
9
+ empty = false,
10
+ emptyText = "Nothing here yet.",
11
+ emptyIcon,
12
+ emptyHeight = 160,
13
+ className = "",
14
+ style,
15
+ children
16
+ }) {
17
+ const sub = subtitle ?? description;
18
+
19
+ return (
20
+ <section className={className} style={style}>
21
+ {(title || sub || actions) && (
22
+ <div className="mb-4 flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
23
+ <div className="min-w-0">
24
+ {title && (
25
+ <UIText as="h2" size="lg" weight="bold" className="truncate">
26
+ {title}
27
+ </UIText>
28
+ )}
29
+ {sub && (
30
+ <UIText as="p" size="sm" muted className="mt-1">
31
+ {sub}
32
+ </UIText>
33
+ )}
34
+ </div>
35
+ {actions && <div className="flex shrink-0 items-center gap-2">{actions}</div>}
36
+ </div>
37
+ )}
38
+
39
+ {empty ? (
40
+ <div
41
+ className="flex w-full flex-col items-center justify-center rounded-2xl border border-dashed border-slate-300 bg-slate-50 px-6 text-center dark:border-slate-700 dark:bg-slate-900/40"
42
+ style={{ minHeight: emptyHeight }}
43
+ >
44
+ {emptyIcon ? <div className="mb-2">{emptyIcon}</div> : null}
45
+ <UIText size="sm" muted>
46
+ {emptyText}
47
+ </UIText>
48
+ </div>
49
+ ) : (
50
+ children
51
+ )}
52
+ </section>
53
+ );
54
+ }
55
+
56
+
@@ -0,0 +1,34 @@
1
+ import * as React from "react";
2
+ import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
3
+
4
+ // Simplified DatePicker components
5
+ // Full implementation would use react-day-picker
6
+
7
+ function DatePicker({ children, ...props }: { children: React.ReactNode } & React.ComponentProps<typeof Popover>) {
8
+ return <Popover {...props}>{children}</Popover>;
9
+ }
10
+
11
+ function DatePickerTrigger({ ...props }: React.ComponentProps<typeof PopoverTrigger>) {
12
+ return <PopoverTrigger {...props} />;
13
+ }
14
+
15
+ function DatePickerContent({ ...props }: React.ComponentProps<typeof PopoverContent>) {
16
+ return <PopoverContent {...props} />;
17
+ }
18
+
19
+ function DatePickerCalendar({ ...props }: any) {
20
+ // Simplified calendar placeholder
21
+ return <div {...props}>Calendar component</div>;
22
+ }
23
+
24
+ function DatePickerRangeTrigger({ ...props }: React.ComponentProps<typeof PopoverTrigger>) {
25
+ return <PopoverTrigger {...props} />;
26
+ }
27
+
28
+ export {
29
+ DatePicker,
30
+ DatePickerTrigger,
31
+ DatePickerContent,
32
+ DatePickerCalendar,
33
+ DatePickerRangeTrigger,
34
+ };
@@ -0,0 +1,141 @@
1
+ import * as React from "react";
2
+ import { Dialog as DialogPrimitive } from "radix-ui";
3
+
4
+ function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
5
+ return <DialogPrimitive.Root {...props} />;
6
+ }
7
+
8
+ function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
9
+ return <DialogPrimitive.Trigger {...props} />;
10
+ }
11
+
12
+ function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
13
+ return <DialogPrimitive.Portal {...props} />;
14
+ }
15
+
16
+ function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
17
+ return <DialogPrimitive.Close {...props} />;
18
+ }
19
+
20
+ function DialogOverlay({
21
+ className,
22
+ ...props
23
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
24
+ return (
25
+ <DialogPrimitive.Overlay
26
+ className={[
27
+ "fixed inset-0 z-50 bg-black/50",
28
+ className
29
+ ].filter(Boolean).join(" ")}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function DialogContent({
36
+ className,
37
+ children,
38
+ showCloseButton = true,
39
+ ...props
40
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & { showCloseButton?: boolean }) {
41
+ return (
42
+ <DialogPortal>
43
+ <DialogOverlay />
44
+ <DialogPrimitive.Content
45
+ className={[
46
+ "fixed left-1/2 top-1/2 z-50 max-h-[85vh] w-[90vw] max-w-[500px] -translate-x-1/2 -translate-y-1/2",
47
+ "rounded-lg border border-slate-200 bg-white p-6 shadow-lg",
48
+ "dark:border-slate-800 dark:bg-slate-900",
49
+ className
50
+ ].filter(Boolean).join(" ")}
51
+ {...props}
52
+ >
53
+ {children}
54
+ {showCloseButton && (
55
+ <DialogClose className="absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100">
56
+ <span className="sr-only">Close</span>
57
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
58
+ <path
59
+ d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
60
+ fill="currentColor"
61
+ />
62
+ </svg>
63
+ </DialogClose>
64
+ )}
65
+ </DialogPrimitive.Content>
66
+ </DialogPortal>
67
+ );
68
+ }
69
+
70
+ function DialogHeader({
71
+ className,
72
+ ...props
73
+ }: React.ComponentProps<"div">) {
74
+ return (
75
+ <div
76
+ className={[
77
+ "flex flex-col space-y-1.5 text-center sm:text-left",
78
+ className
79
+ ].filter(Boolean).join(" ")}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ function DialogFooter({
86
+ className,
87
+ ...props
88
+ }: React.ComponentProps<"div">) {
89
+ return (
90
+ <div
91
+ className={[
92
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
93
+ className
94
+ ].filter(Boolean).join(" ")}
95
+ {...props}
96
+ />
97
+ );
98
+ }
99
+
100
+ function DialogTitle({
101
+ className,
102
+ ...props
103
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
104
+ return (
105
+ <DialogPrimitive.Title
106
+ className={[
107
+ "text-lg font-semibold leading-none tracking-tight",
108
+ className
109
+ ].filter(Boolean).join(" ")}
110
+ {...props}
111
+ />
112
+ );
113
+ }
114
+
115
+ function DialogDescription({
116
+ className,
117
+ ...props
118
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
119
+ return (
120
+ <DialogPrimitive.Description
121
+ className={[
122
+ "text-sm text-slate-500 dark:text-slate-400",
123
+ className
124
+ ].filter(Boolean).join(" ")}
125
+ {...props}
126
+ />
127
+ );
128
+ }
129
+
130
+ export {
131
+ Dialog,
132
+ DialogTrigger,
133
+ DialogPortal,
134
+ DialogClose,
135
+ DialogOverlay,
136
+ DialogContent,
137
+ DialogHeader,
138
+ DialogFooter,
139
+ DialogTitle,
140
+ DialogDescription,
141
+ };
@@ -0,0 +1,46 @@
1
+ import React from "react";
2
+
3
+ const SIZES = {
4
+ sm: { icon: "h-8 w-8", heading: "text-sm", body: "text-xs", gap: "gap-2", pad: "py-6" },
5
+ md: { icon: "h-10 w-10", heading: "text-base", body: "text-sm", gap: "gap-3", pad: "py-10" },
6
+ lg: { icon: "h-14 w-14", heading: "text-lg", body: "text-sm", gap: "gap-4", pad: "py-16" },
7
+ };
8
+
9
+ /**
10
+ * Empty state placeholder — shows when a list, table, or section has no content.
11
+ *
12
+ * @param {ReactNode} icon Optional icon element
13
+ * @param {string} heading Primary message
14
+ * @param {string} body Secondary description
15
+ * @param {ReactNode} action Optional CTA (button, link, etc.)
16
+ * @param {"sm"|"md"|"lg"} size Visual density
17
+ */
18
+ export default function EmptyState({
19
+ icon,
20
+ heading = "Nothing here yet",
21
+ body,
22
+ action,
23
+ size = "md",
24
+ className = "",
25
+ }) {
26
+ const s = SIZES[size] ?? SIZES.md;
27
+
28
+ return (
29
+ <div className={`flex flex-col items-center justify-center text-center ${s.pad} ${s.gap} ${className}`}>
30
+ {icon && (
31
+ <div className={`${s.icon} text-slate-300 dark:text-slate-600`}>
32
+ {icon}
33
+ </div>
34
+ )}
35
+ <div className={`${s.heading} font-semibold text-slate-700 dark:text-slate-200`}>
36
+ {heading}
37
+ </div>
38
+ {body && (
39
+ <div className={`${s.body} max-w-sm text-slate-500 dark:text-slate-400`}>
40
+ {body}
41
+ </div>
42
+ )}
43
+ {action && <div className="mt-1">{action}</div>}
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,82 @@
1
+ import * as React from "react";
2
+
3
+ function Field({
4
+ className,
5
+ children,
6
+ ...props
7
+ }: React.ComponentProps<"div">) {
8
+ return (
9
+ <div
10
+ className={[
11
+ "flex flex-col gap-1.5",
12
+ className
13
+ ].filter(Boolean).join(" ")}
14
+ {...props}
15
+ >
16
+ {children}
17
+ </div>
18
+ );
19
+ }
20
+
21
+ function FieldLabel({
22
+ className,
23
+ htmlFor,
24
+ children,
25
+ ...props
26
+ }: React.ComponentProps<"label">) {
27
+ return (
28
+ <label
29
+ htmlFor={htmlFor}
30
+ className={[
31
+ "block text-sm font-medium text-slate-700 dark:text-slate-200",
32
+ className
33
+ ].filter(Boolean).join(" ")}
34
+ {...props}
35
+ >
36
+ {children}
37
+ </label>
38
+ );
39
+ }
40
+
41
+ function FieldDescription({
42
+ className,
43
+ children,
44
+ ...props
45
+ }: React.ComponentProps<"p">) {
46
+ return (
47
+ <p
48
+ className={[
49
+ "text-xs text-slate-500 dark:text-slate-400",
50
+ className
51
+ ].filter(Boolean).join(" ")}
52
+ {...props}
53
+ >
54
+ {children}
55
+ </p>
56
+ );
57
+ }
58
+
59
+ function FieldError({
60
+ className,
61
+ children,
62
+ ...props
63
+ }: React.ComponentProps<"p">) {
64
+ return (
65
+ <p
66
+ className={[
67
+ "text-xs text-red-600 dark:text-red-400",
68
+ className
69
+ ].filter(Boolean).join(" ")}
70
+ {...props}
71
+ >
72
+ {children}
73
+ </p>
74
+ );
75
+ }
76
+
77
+ export {
78
+ Field,
79
+ FieldLabel,
80
+ FieldDescription,
81
+ FieldError,
82
+ };
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+
3
+ export default function FieldGroup({ className = "", children, ...rest }) {
4
+ return (
5
+ <div
6
+ className={[
7
+ "flex flex-col gap-1.5",
8
+ className
9
+ ]
10
+ .filter(Boolean)
11
+ .join(" ")}
12
+ {...rest}
13
+ >
14
+ {children}
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+
3
+ export default function UIInput({ style = undefined, className = "", ...rest }) {
4
+ return (
5
+ <input
6
+ style={style}
7
+ className={[
8
+ "h-10 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 shadow-sm",
9
+ "placeholder:text-slate-400",
10
+ "focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 dark:focus:ring-offset-slate-950",
11
+ "dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50 dark:placeholder:text-slate-500",
12
+ className
13
+ ]
14
+ .filter(Boolean)
15
+ .join(" ")}
16
+ {...rest}
17
+ />
18
+ );
19
+ }
20
+
21
+
@@ -0,0 +1,22 @@
1
+ import React from "react";
2
+
3
+ export default function Label({ children, htmlFor, required, className = "", ...rest }) {
4
+ // If no htmlFor provided, render as div for compatibility
5
+ const Tag = htmlFor ? 'label' : 'div';
6
+ const props = htmlFor ? { htmlFor, ...rest } : rest;
7
+
8
+ return (
9
+ <Tag
10
+ {...props}
11
+ className={[
12
+ "text-sm font-medium text-slate-700 dark:text-slate-200",
13
+ className
14
+ ]
15
+ .filter(Boolean)
16
+ .join(" ")}
17
+ >
18
+ {children}
19
+ {required && <span className="ml-0.5 text-red-500">*</span>}
20
+ </Tag>
21
+ );
22
+ }
@@ -0,0 +1,142 @@
1
+ import * as React from "react";
2
+ import { Link } from "react-router-dom";
3
+
4
+ // Shadcn-style Pagination subcomponents
5
+
6
+ function PaginationContent({ className, children, ...props }: React.ComponentProps<"ul">) {
7
+ return (
8
+ <ul
9
+ className={[
10
+ "flex flex-row items-center gap-1",
11
+ className
12
+ ].filter(Boolean).join(" ")}
13
+ {...props}
14
+ >
15
+ {children}
16
+ </ul>
17
+ );
18
+ }
19
+
20
+ function PaginationItem({ className, children, ...props }: React.ComponentProps<"li">) {
21
+ return (
22
+ <li
23
+ className={className}
24
+ {...props}
25
+ >
26
+ {children}
27
+ </li>
28
+ );
29
+ }
30
+
31
+ function PaginationLink({
32
+ className,
33
+ isActive,
34
+ size = "default",
35
+ ...props
36
+ }: React.ComponentProps<typeof Link> & {
37
+ isActive?: boolean;
38
+ size?: "default" | "sm" | "lg";
39
+ }) {
40
+ const sizeClasses = {
41
+ default: "h-9 min-w-9 px-4 py-2",
42
+ sm: "h-8 min-w-8 px-3 py-1.5 text-sm",
43
+ lg: "h-11 min-w-11 px-8 py-3"
44
+ };
45
+
46
+ return (
47
+ <Link
48
+ aria-current={isActive ? "page" : undefined}
49
+ className={[
50
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
51
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500",
52
+ "disabled:pointer-events-none disabled:opacity-50",
53
+ isActive
54
+ ? "bg-slate-900 text-white dark:bg-slate-50 dark:text-slate-900"
55
+ : "hover:bg-slate-100 dark:hover:bg-slate-800",
56
+ sizeClasses[size],
57
+ className
58
+ ].filter(Boolean).join(" ")}
59
+ {...props}
60
+ />
61
+ );
62
+ }
63
+
64
+ function PaginationPrevious({
65
+ className,
66
+ ...props
67
+ }: React.ComponentProps<typeof PaginationLink>) {
68
+ return (
69
+ <PaginationLink
70
+ aria-label="Go to previous page"
71
+ size="default"
72
+ className={[
73
+ "gap-1 pl-2.5",
74
+ className
75
+ ].filter(Boolean).join(" ")}
76
+ {...props}
77
+ >
78
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
79
+ <path
80
+ d="M8.84182 3.13514C9.04327 3.32401 9.05348 3.64042 8.86462 3.84188L5.43521 7.49991L8.86462 11.1579C9.05348 11.3594 9.04327 11.6758 8.84182 11.8647C8.64036 12.0535 8.32394 12.0433 8.13508 11.8419L4.38508 7.84188C4.20477 7.64955 4.20477 7.35027 4.38508 7.15794L8.13508 3.15794C8.32394 2.95648 8.64036 2.94628 8.84182 3.13514Z"
81
+ fill="currentColor"
82
+ />
83
+ </svg>
84
+ <span>Previous</span>
85
+ </PaginationLink>
86
+ );
87
+ }
88
+
89
+ function PaginationNext({
90
+ className,
91
+ ...props
92
+ }: React.ComponentProps<typeof PaginationLink>) {
93
+ return (
94
+ <PaginationLink
95
+ aria-label="Go to next page"
96
+ size="default"
97
+ className={[
98
+ "gap-1 pr-2.5",
99
+ className
100
+ ].filter(Boolean).join(" ")}
101
+ {...props}
102
+ >
103
+ <span>Next</span>
104
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
105
+ <path
106
+ d="M6.1584 3.13514C6.35985 2.94628 6.67627 2.95648 6.86513 3.15794L10.6151 7.15794C10.7954 7.35027 10.7954 7.64955 10.6151 7.84188L6.86513 11.8419C6.67627 12.0433 6.35985 12.0535 6.1584 11.8647C5.95694 11.6758 5.94673 11.3594 6.13559 11.1579L9.565 7.49991L6.13559 3.84188C5.94673 3.64042 5.95694 3.32401 6.1584 3.13514Z"
107
+ fill="currentColor"
108
+ />
109
+ </svg>
110
+ </PaginationLink>
111
+ );
112
+ }
113
+
114
+ function PaginationEllipsis({ className, ...props }: React.ComponentProps<"span">) {
115
+ return (
116
+ <span
117
+ aria-hidden
118
+ className={[
119
+ "flex h-9 w-9 items-center justify-center",
120
+ className
121
+ ].filter(Boolean).join(" ")}
122
+ {...props}
123
+ >
124
+ <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
125
+ <path
126
+ d="M3.625 7.5C3.625 8.12132 3.12132 8.625 2.5 8.625C1.87868 8.625 1.375 8.12132 1.375 7.5C1.375 6.87868 1.87868 6.375 2.5 6.375C3.12132 6.375 3.625 6.87868 3.625 7.5ZM8.625 7.5C8.625 8.12132 8.12132 8.625 7.5 8.625C6.87868 8.625 6.375 8.12132 6.375 7.5C6.375 6.87868 6.87868 6.375 7.5 6.375C8.12132 6.375 8.625 6.87868 8.625 7.5ZM12.5 8.625C13.1213 8.625 13.625 8.12132 13.625 7.5C13.625 6.87868 13.1213 6.375 12.5 6.375C11.8787 6.375 11.375 6.87868 11.375 7.5C11.375 8.12132 11.8787 8.625 12.5 8.625Z"
127
+ fill="currentColor"
128
+ />
129
+ </svg>
130
+ <span className="sr-only">More pages</span>
131
+ </span>
132
+ );
133
+ }
134
+
135
+ export {
136
+ PaginationContent,
137
+ PaginationItem,
138
+ PaginationLink,
139
+ PaginationPrevious,
140
+ PaginationNext,
141
+ PaginationEllipsis,
142
+ };
@@ -0,0 +1,39 @@
1
+ import * as React from "react";
2
+ import { Popover as PopoverPrimitive } from "radix-ui";
3
+
4
+ function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
5
+ return <PopoverPrimitive.Root {...props} />;
6
+ }
7
+
8
+ function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
9
+ return <PopoverPrimitive.Trigger {...props} />;
10
+ }
11
+
12
+ function PopoverContent({
13
+ className,
14
+ align = "center",
15
+ sideOffset = 4,
16
+ ...props
17
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
18
+ return (
19
+ <PopoverPrimitive.Portal>
20
+ <PopoverPrimitive.Content
21
+ align={align}
22
+ sideOffset={sideOffset}
23
+ className={[
24
+ "z-50 w-72 rounded-md border border-slate-200 bg-white p-4 text-slate-900 shadow-md outline-none",
25
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
26
+ "dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50",
27
+ className
28
+ ].filter(Boolean).join(" ")}
29
+ {...props}
30
+ />
31
+ </PopoverPrimitive.Portal>
32
+ );
33
+ }
34
+
35
+ export {
36
+ Popover,
37
+ PopoverTrigger,
38
+ PopoverContent,
39
+ };