@salesforce/ui-bundle-template-feature-react-agentforce-conversation-client 1.117.2

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 (98) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +149 -0
  3. package/dist/.forceignore +15 -0
  4. package/dist/.husky/pre-commit +4 -0
  5. package/dist/.prettierignore +11 -0
  6. package/dist/.prettierrc +17 -0
  7. package/dist/AGENT.md +193 -0
  8. package/dist/CHANGELOG.md +2128 -0
  9. package/dist/README.md +28 -0
  10. package/dist/config/project-scratch-def.json +13 -0
  11. package/dist/eslint.config.js +7 -0
  12. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/.forceignore +15 -0
  13. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/.graphqlrc.yml +2 -0
  14. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/.prettierignore +9 -0
  15. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/.prettierrc +11 -0
  16. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/CHANGELOG.md +10 -0
  17. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/README.md +75 -0
  18. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/codegen.yml +95 -0
  19. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/components.json +18 -0
  20. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/e2e/app.spec.ts +17 -0
  21. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/eslint.config.js +169 -0
  22. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/feature-react-agentforce-conversation-client.uibundle-meta.xml +7 -0
  23. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/index.html +12 -0
  24. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/package.json +69 -0
  25. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/playwright.config.ts +24 -0
  26. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/scripts/get-graphql-schema.mjs +68 -0
  27. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/scripts/rewrite-e2e-assets.mjs +23 -0
  28. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/api/graphqlClient.ts +25 -0
  29. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/app.tsx +17 -0
  30. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/appLayout.tsx +83 -0
  31. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/icons/book.svg +3 -0
  32. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/icons/copy.svg +4 -0
  33. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/icons/rocket.svg +3 -0
  34. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/icons/star.svg +3 -0
  35. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/images/codey-1.png +0 -0
  36. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/images/codey-2.png +0 -0
  37. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/images/codey-3.png +0 -0
  38. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/assets/images/vibe-codey.svg +194 -0
  39. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/AgentforceConversationClient.tsx +168 -0
  40. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/alerts/status-alert.tsx +49 -0
  41. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/layouts/card-layout.tsx +29 -0
  42. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/alert.tsx +76 -0
  43. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/badge.tsx +48 -0
  44. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/breadcrumb.tsx +109 -0
  45. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/button.tsx +67 -0
  46. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/calendar.tsx +232 -0
  47. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/card.tsx +103 -0
  48. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/checkbox.tsx +32 -0
  49. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/collapsible.tsx +33 -0
  50. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/datePicker.tsx +127 -0
  51. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/dialog.tsx +162 -0
  52. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/field.tsx +237 -0
  53. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/index.ts +84 -0
  54. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/input.tsx +19 -0
  55. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/label.tsx +22 -0
  56. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/pagination.tsx +132 -0
  57. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/popover.tsx +89 -0
  58. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/select.tsx +193 -0
  59. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/separator.tsx +26 -0
  60. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/skeleton.tsx +14 -0
  61. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/sonner.tsx +20 -0
  62. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/spinner.tsx +16 -0
  63. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/table.tsx +114 -0
  64. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/ui/tabs.tsx +88 -0
  65. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/index.ts +6 -0
  66. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/lib/utils.ts +6 -0
  67. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/navigationMenu.tsx +80 -0
  68. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/pages/Home.tsx +12 -0
  69. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/pages/NotFound.tsx +18 -0
  70. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/pages/TestAccPage.tsx +19 -0
  71. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/router-utils.tsx +35 -0
  72. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/routes.tsx +28 -0
  73. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/styles/global.css +135 -0
  74. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/types/conversation.ts +33 -0
  75. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/tsconfig.json +42 -0
  76. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/tsconfig.node.json +13 -0
  77. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/ui-bundle.json +7 -0
  78. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/vite-env.d.ts +1 -0
  79. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/vite.config.ts +106 -0
  80. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/vitest-env.d.ts +2 -0
  81. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/vitest.config.ts +11 -0
  82. package/dist/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/vitest.setup.ts +1 -0
  83. package/dist/jest.config.js +6 -0
  84. package/dist/package-lock.json +9995 -0
  85. package/dist/package.json +40 -0
  86. package/dist/scripts/apex/hello.apex +10 -0
  87. package/dist/scripts/graphql-search.sh +191 -0
  88. package/dist/scripts/prepare-import-unique-fields.js +122 -0
  89. package/dist/scripts/setup-cli.mjs +563 -0
  90. package/dist/scripts/sf-project-setup.mjs +66 -0
  91. package/dist/scripts/soql/account.soql +6 -0
  92. package/dist/sfdx-project.json +12 -0
  93. package/package.json +54 -0
  94. package/src/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/components/AgentforceConversationClient.tsx +168 -0
  95. package/src/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/index.ts +6 -0
  96. package/src/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/pages/TestAccPage.tsx +19 -0
  97. package/src/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/routes.tsx +23 -0
  98. package/src/force-app/main/default/uiBundles/feature-react-agentforce-conversation-client/src/types/conversation.ts +33 -0
@@ -0,0 +1,237 @@
1
+ import * as React from 'react';
2
+ import { useMemo } from 'react';
3
+ import { cva, type VariantProps } from 'class-variance-authority';
4
+
5
+ import { cn } from '../../lib/utils';
6
+ import { Label } from './label';
7
+ import { Separator } from './separator';
8
+
9
+ function FieldSet({ className, ...props }: React.ComponentProps<'fieldset'>) {
10
+ return (
11
+ <fieldset
12
+ data-slot="field-set"
13
+ className={cn(
14
+ 'gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col',
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+
22
+ function FieldLegend({
23
+ className,
24
+ variant = 'legend',
25
+ ...props
26
+ }: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
27
+ return (
28
+ <legend
29
+ data-slot="field-legend"
30
+ data-variant={variant}
31
+ className={cn(
32
+ 'mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base',
33
+ className
34
+ )}
35
+ {...props}
36
+ />
37
+ );
38
+ }
39
+
40
+ function FieldGroup({ className, ...props }: React.ComponentProps<'div'>) {
41
+ return (
42
+ <div
43
+ data-slot="field-group"
44
+ className={cn(
45
+ 'gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4 group/field-group @container/field-group flex w-full flex-col',
46
+ className
47
+ )}
48
+ {...props}
49
+ />
50
+ );
51
+ }
52
+
53
+ const fieldVariants = cva(
54
+ 'data-[invalid=true]:text-destructive gap-2 group/field flex w-full',
55
+ {
56
+ variants: {
57
+ orientation: {
58
+ vertical: 'flex-col *:w-full [&>.sr-only]:w-auto',
59
+ horizontal:
60
+ 'flex-row items-center *:data-[slot=field-label]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
61
+ responsive:
62
+ 'flex-col *:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:*:w-auto @md/field-group:*:data-[slot=field-label]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px',
63
+ },
64
+ },
65
+ defaultVariants: {
66
+ orientation: 'vertical',
67
+ },
68
+ }
69
+ );
70
+
71
+ function Field({
72
+ className,
73
+ orientation = 'vertical',
74
+ ...props
75
+ }: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) {
76
+ return (
77
+ <div
78
+ role="group"
79
+ data-slot="field"
80
+ data-orientation={orientation}
81
+ className={cn(fieldVariants({ orientation }), className)}
82
+ {...props}
83
+ />
84
+ );
85
+ }
86
+
87
+ function FieldContent({ className, ...props }: React.ComponentProps<'div'>) {
88
+ return (
89
+ <div
90
+ data-slot="field-content"
91
+ className={cn(
92
+ 'gap-0.5 group/field-content flex flex-1 flex-col leading-snug',
93
+ className
94
+ )}
95
+ {...props}
96
+ />
97
+ );
98
+ }
99
+
100
+ function FieldLabel({
101
+ className,
102
+ ...props
103
+ }: React.ComponentProps<typeof Label>) {
104
+ return (
105
+ <Label
106
+ data-slot="field-label"
107
+ className={cn(
108
+ 'has-data-checked:bg-primary/5 has-data-checked:border-primary/30 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10 gap-2 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 group/field-label peer/field-label flex w-fit leading-snug',
109
+ 'has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col',
110
+ className
111
+ )}
112
+ {...props}
113
+ />
114
+ );
115
+ }
116
+
117
+ function FieldTitle({ className, ...props }: React.ComponentProps<'div'>) {
118
+ return (
119
+ <div
120
+ data-slot="field-label"
121
+ className={cn(
122
+ 'gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug',
123
+ className
124
+ )}
125
+ {...props}
126
+ />
127
+ );
128
+ }
129
+
130
+ function FieldDescription({ className, ...props }: React.ComponentProps<'p'>) {
131
+ return (
132
+ <p
133
+ data-slot="field-description"
134
+ className={cn(
135
+ 'text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-data-horizontal/field:text-balance',
136
+ 'last:mt-0 nth-last-2:-mt-1',
137
+ '[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
138
+ className
139
+ )}
140
+ {...props}
141
+ />
142
+ );
143
+ }
144
+
145
+ function FieldSeparator({
146
+ children,
147
+ className,
148
+ ...props
149
+ }: React.ComponentProps<'div'> & {
150
+ children?: React.ReactNode;
151
+ }) {
152
+ return (
153
+ <div
154
+ data-slot="field-separator"
155
+ data-content={!!children}
156
+ className={cn(
157
+ '-my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2 relative',
158
+ className
159
+ )}
160
+ {...props}
161
+ >
162
+ <Separator className="absolute inset-0 top-1/2" />
163
+ {children && (
164
+ <span
165
+ className="text-muted-foreground px-2 bg-background relative mx-auto block w-fit"
166
+ data-slot="field-separator-content"
167
+ >
168
+ {children}
169
+ </span>
170
+ )}
171
+ </div>
172
+ );
173
+ }
174
+
175
+ function FieldError({
176
+ className,
177
+ children,
178
+ errors,
179
+ ...props
180
+ }: React.ComponentProps<'div'> & {
181
+ errors?: Array<{ message?: string } | undefined>;
182
+ }) {
183
+ const content = useMemo(() => {
184
+ if (children) {
185
+ return children;
186
+ }
187
+
188
+ if (!errors?.length) {
189
+ return null;
190
+ }
191
+
192
+ const uniqueErrors = [
193
+ ...new Map(errors.map(error => [error?.message, error])).values(),
194
+ ];
195
+
196
+ if (uniqueErrors?.length == 1) {
197
+ return uniqueErrors[0]?.message;
198
+ }
199
+
200
+ return (
201
+ <ul className="ml-4 flex list-disc flex-col gap-1">
202
+ {uniqueErrors.map(
203
+ (error, index) =>
204
+ error?.message && <li key={index}>{error.message}</li>
205
+ )}
206
+ </ul>
207
+ );
208
+ }, [children, errors]);
209
+
210
+ if (!content) {
211
+ return null;
212
+ }
213
+
214
+ return (
215
+ <div
216
+ role="alert"
217
+ data-slot="field-error"
218
+ className={cn('text-destructive text-sm font-normal', className)}
219
+ {...props}
220
+ >
221
+ {content}
222
+ </div>
223
+ );
224
+ }
225
+
226
+ export {
227
+ Field,
228
+ FieldLabel,
229
+ FieldDescription,
230
+ FieldError,
231
+ FieldGroup,
232
+ FieldLegend,
233
+ FieldSeparator,
234
+ FieldSet,
235
+ FieldContent,
236
+ FieldTitle,
237
+ };
@@ -0,0 +1,84 @@
1
+ /**
2
+ * UI Components Index
3
+ *
4
+ * Re-exports all UI components for easier imports.
5
+ *
6
+ * Usage:
7
+ * import { Button, Input, Tabs } from "@/components/ui"
8
+ *
9
+ * Instead of:
10
+ * import { Button } from "@/components/ui/button"
11
+ * import { Input } from "@/components/ui/input"
12
+ * import { Tabs } from "@/components/ui/tabs"
13
+ */
14
+
15
+ export { Alert, AlertTitle, AlertDescription, AlertAction } from './alert';
16
+ export { Button, buttonVariants } from './button';
17
+ export {
18
+ Card,
19
+ CardHeader,
20
+ CardFooter,
21
+ CardTitle,
22
+ CardAction,
23
+ CardDescription,
24
+ CardContent,
25
+ } from './card';
26
+ export {
27
+ Dialog,
28
+ DialogClose,
29
+ DialogContent,
30
+ DialogDescription,
31
+ DialogFooter,
32
+ DialogHeader,
33
+ DialogOverlay,
34
+ DialogPortal,
35
+ DialogTitle,
36
+ DialogTrigger,
37
+ } from './dialog';
38
+ export {
39
+ Field,
40
+ FieldDescription,
41
+ FieldError,
42
+ FieldGroup,
43
+ FieldLabel,
44
+ FieldLegend,
45
+ FieldSeparator,
46
+ FieldSet,
47
+ } from './field';
48
+ export { Input } from './input';
49
+ export { Label } from './label';
50
+ export {
51
+ Select,
52
+ SelectGroup,
53
+ SelectValue,
54
+ SelectTrigger,
55
+ SelectContent,
56
+ SelectLabel,
57
+ SelectItem,
58
+ SelectSeparator,
59
+ SelectScrollUpButton,
60
+ SelectScrollDownButton,
61
+ } from './select';
62
+ export { Spinner } from './spinner';
63
+ export { Skeleton } from './skeleton';
64
+ export {
65
+ Table,
66
+ TableHeader,
67
+ TableBody,
68
+ TableFooter,
69
+ TableHead,
70
+ TableRow,
71
+ TableCell,
72
+ TableCaption,
73
+ } from './table';
74
+ export { Tabs, TabsList, TabsTrigger, TabsContent } from './tabs';
75
+ export {
76
+ Pagination,
77
+ PaginationContent,
78
+ PaginationEllipsis,
79
+ PaginationItem,
80
+ PaginationLink,
81
+ PaginationNext,
82
+ PaginationPrevious,
83
+ } from './pagination';
84
+ export { Separator } from './separator';
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '../../lib/utils';
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ 'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors file:h-6 file:text-sm file:font-medium focus-visible:ring-3 aria-invalid:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
12
+ className
13
+ )}
14
+ {...props}
15
+ />
16
+ );
17
+ }
18
+
19
+ export { Input };
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+ import { Label as LabelPrimitive } from 'radix-ui';
3
+
4
+ import { cn } from '../../lib/utils';
5
+
6
+ function Label({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
10
+ return (
11
+ <LabelPrimitive.Root
12
+ data-slot="label"
13
+ className={cn(
14
+ 'gap-2 text-sm leading-none font-medium group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed',
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+
22
+ export { Label };
@@ -0,0 +1,132 @@
1
+ import * as React from 'react';
2
+
3
+ import { cn } from '../../lib/utils';
4
+ import { Button } from './button';
5
+ import {
6
+ ChevronLeftIcon,
7
+ ChevronRightIcon,
8
+ MoreHorizontalIcon,
9
+ } from 'lucide-react';
10
+
11
+ function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
12
+ return (
13
+ <nav
14
+ role="navigation"
15
+ aria-label="pagination"
16
+ data-slot="pagination"
17
+ className={cn('mx-auto flex w-full justify-center', className)}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+
23
+ function PaginationContent({
24
+ className,
25
+ ...props
26
+ }: React.ComponentProps<'ul'>) {
27
+ return (
28
+ <ul
29
+ data-slot="pagination-content"
30
+ className={cn('gap-0.5 flex items-center', className)}
31
+ {...props}
32
+ />
33
+ );
34
+ }
35
+
36
+ function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
37
+ return <li data-slot="pagination-item" {...props} />;
38
+ }
39
+
40
+ type PaginationLinkProps = {
41
+ isActive?: boolean;
42
+ } & Pick<React.ComponentProps<typeof Button>, 'size'> &
43
+ React.ComponentProps<'a'>;
44
+
45
+ function PaginationLink({
46
+ className,
47
+ isActive,
48
+ size = 'icon',
49
+ ...props
50
+ }: PaginationLinkProps) {
51
+ return (
52
+ <Button
53
+ asChild
54
+ variant={isActive ? 'outline' : 'ghost'}
55
+ size={size}
56
+ className={cn(className)}
57
+ >
58
+ <a
59
+ aria-current={isActive ? 'page' : undefined}
60
+ data-slot="pagination-link"
61
+ data-active={isActive}
62
+ {...props}
63
+ />
64
+ </Button>
65
+ );
66
+ }
67
+
68
+ function PaginationPrevious({
69
+ className,
70
+ text = 'Previous',
71
+ ...props
72
+ }: React.ComponentProps<typeof PaginationLink> & { text?: string }) {
73
+ return (
74
+ <PaginationLink
75
+ aria-label="Go to previous page"
76
+ size="default"
77
+ className={cn('pl-1.5!', className)}
78
+ {...props}
79
+ >
80
+ <ChevronLeftIcon data-icon="inline-start" className="cn-rtl-flip" />
81
+ <span className="hidden sm:block">{text}</span>
82
+ </PaginationLink>
83
+ );
84
+ }
85
+
86
+ function PaginationNext({
87
+ className,
88
+ text = 'Next',
89
+ ...props
90
+ }: React.ComponentProps<typeof PaginationLink> & { text?: string }) {
91
+ return (
92
+ <PaginationLink
93
+ aria-label="Go to next page"
94
+ size="default"
95
+ className={cn('pr-1.5!', className)}
96
+ {...props}
97
+ >
98
+ <span className="hidden sm:block">{text}</span>
99
+ <ChevronRightIcon data-icon="inline-end" className="cn-rtl-flip" />
100
+ </PaginationLink>
101
+ );
102
+ }
103
+
104
+ function PaginationEllipsis({
105
+ className,
106
+ ...props
107
+ }: React.ComponentProps<'span'>) {
108
+ return (
109
+ <span
110
+ aria-hidden
111
+ data-slot="pagination-ellipsis"
112
+ className={cn(
113
+ "size-8 [&_svg:not([class*='size-'])]:size-4 flex items-center justify-center",
114
+ className
115
+ )}
116
+ {...props}
117
+ >
118
+ <MoreHorizontalIcon />
119
+ <span className="sr-only">More pages</span>
120
+ </span>
121
+ );
122
+ }
123
+
124
+ export {
125
+ Pagination,
126
+ PaginationContent,
127
+ PaginationEllipsis,
128
+ PaginationItem,
129
+ PaginationLink,
130
+ PaginationNext,
131
+ PaginationPrevious,
132
+ };
@@ -0,0 +1,89 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Popover as PopoverPrimitive } from 'radix-ui';
5
+
6
+ import { cn } from '@/lib/utils';
7
+
8
+ function Popover({
9
+ ...props
10
+ }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
11
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />;
12
+ }
13
+
14
+ function PopoverTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
17
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
18
+ }
19
+
20
+ function PopoverContent({
21
+ className,
22
+ align = 'center',
23
+ sideOffset = 4,
24
+ ...props
25
+ }: React.ComponentProps<typeof PopoverPrimitive.Content>) {
26
+ return (
27
+ <PopoverPrimitive.Portal>
28
+ <PopoverPrimitive.Content
29
+ data-slot="popover-content"
30
+ align={align}
31
+ sideOffset={sideOffset}
32
+ className={cn(
33
+ 'bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--radix-popover-content-transform-origin) outline-hidden',
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ </PopoverPrimitive.Portal>
39
+ );
40
+ }
41
+
42
+ function PopoverAnchor({
43
+ ...props
44
+ }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
45
+ return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
46
+ }
47
+
48
+ function PopoverHeader({ className, ...props }: React.ComponentProps<'div'>) {
49
+ return (
50
+ <div
51
+ data-slot="popover-header"
52
+ className={cn('flex flex-col gap-0.5 text-sm', className)}
53
+ {...props}
54
+ />
55
+ );
56
+ }
57
+
58
+ function PopoverTitle({ className, ...props }: React.ComponentProps<'h2'>) {
59
+ return (
60
+ <div
61
+ data-slot="popover-title"
62
+ className={cn('font-medium', className)}
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ function PopoverDescription({
69
+ className,
70
+ ...props
71
+ }: React.ComponentProps<'p'>) {
72
+ return (
73
+ <p
74
+ data-slot="popover-description"
75
+ className={cn('text-muted-foreground', className)}
76
+ {...props}
77
+ />
78
+ );
79
+ }
80
+
81
+ export {
82
+ Popover,
83
+ PopoverAnchor,
84
+ PopoverContent,
85
+ PopoverDescription,
86
+ PopoverHeader,
87
+ PopoverTitle,
88
+ PopoverTrigger,
89
+ };