@pago-sh/ui 1.0.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.
Files changed (229) hide show
  1. package/.turbo/turbo-build.log +195 -0
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +22 -0
  4. package/components.json +17 -0
  5. package/dist/chunk-2RCGDEGJ.mjs +1 -0
  6. package/dist/chunk-3GDNSYGJ.mjs +1 -0
  7. package/dist/chunk-4TCUGB6E.mjs +1 -0
  8. package/dist/chunk-6XCXQA5L.mjs +1 -0
  9. package/dist/chunk-BBYR3CIF.mjs +1 -0
  10. package/dist/chunk-CFBUY7KY.mjs +1 -0
  11. package/dist/chunk-CHG2VB73.mjs +1 -0
  12. package/dist/chunk-GCVBVZU7.mjs +1 -0
  13. package/dist/chunk-HRGUR4R2.mjs +1 -0
  14. package/dist/chunk-IVU4SSCD.mjs +1 -0
  15. package/dist/chunk-N6WI5TGM.mjs +1 -0
  16. package/dist/chunk-OTKGECM3.mjs +1 -0
  17. package/dist/chunk-SRZFZUN4.mjs +1 -0
  18. package/dist/chunk-VPECET7P.mjs +1 -0
  19. package/dist/chunk-WQPSZXQS.mjs +1 -0
  20. package/dist/chunk-YXNT3UEO.mjs +1 -0
  21. package/dist/components/atoms/Accordion.d.mts +20 -0
  22. package/dist/components/atoms/Accordion.d.ts +20 -0
  23. package/dist/components/atoms/Accordion.js +1 -0
  24. package/dist/components/atoms/Accordion.mjs +1 -0
  25. package/dist/components/atoms/Card.d.mts +18 -0
  26. package/dist/components/atoms/Card.d.ts +18 -0
  27. package/dist/components/atoms/Card.js +1 -0
  28. package/dist/components/atoms/Card.mjs +1 -0
  29. package/dist/components/atoms/Combobox.d.mts +24 -0
  30. package/dist/components/atoms/Combobox.d.ts +24 -0
  31. package/dist/components/atoms/Combobox.js +1 -0
  32. package/dist/components/atoms/Combobox.mjs +1 -0
  33. package/dist/components/atoms/CopyToClipboardInput.d.mts +12 -0
  34. package/dist/components/atoms/CopyToClipboardInput.d.ts +12 -0
  35. package/dist/components/atoms/CopyToClipboardInput.js +1 -0
  36. package/dist/components/atoms/CopyToClipboardInput.mjs +1 -0
  37. package/dist/components/atoms/CountryPicker.d.mts +16 -0
  38. package/dist/components/atoms/CountryPicker.d.ts +16 -0
  39. package/dist/components/atoms/CountryPicker.js +1 -0
  40. package/dist/components/atoms/CountryPicker.mjs +1 -0
  41. package/dist/components/atoms/CountryStatePicker.d.mts +18 -0
  42. package/dist/components/atoms/CountryStatePicker.d.ts +18 -0
  43. package/dist/components/atoms/CountryStatePicker.js +1 -0
  44. package/dist/components/atoms/CountryStatePicker.mjs +1 -0
  45. package/dist/components/atoms/DateTimePicker.d.mts +10 -0
  46. package/dist/components/atoms/DateTimePicker.d.ts +10 -0
  47. package/dist/components/atoms/DateTimePicker.js +1 -0
  48. package/dist/components/atoms/DateTimePicker.mjs +1 -0
  49. package/dist/components/atoms/DropdownMenu.d.mts +22 -0
  50. package/dist/components/atoms/DropdownMenu.d.ts +22 -0
  51. package/dist/components/atoms/DropdownMenu.js +1 -0
  52. package/dist/components/atoms/DropdownMenu.mjs +1 -0
  53. package/dist/components/atoms/FormattedDateTime.d.mts +10 -0
  54. package/dist/components/atoms/FormattedDateTime.d.ts +10 -0
  55. package/dist/components/atoms/FormattedDateTime.js +1 -0
  56. package/dist/components/atoms/FormattedDateTime.mjs +1 -0
  57. package/dist/components/atoms/FormattedInterval.d.mts +9 -0
  58. package/dist/components/atoms/FormattedInterval.d.ts +9 -0
  59. package/dist/components/atoms/FormattedInterval.js +1 -0
  60. package/dist/components/atoms/FormattedInterval.mjs +1 -0
  61. package/dist/components/atoms/InputOTP.d.mts +4 -0
  62. package/dist/components/atoms/InputOTP.d.ts +4 -0
  63. package/dist/components/atoms/InputOTP.js +1 -0
  64. package/dist/components/atoms/InputOTP.mjs +1 -0
  65. package/dist/components/atoms/MoneyInput.d.mts +21 -0
  66. package/dist/components/atoms/MoneyInput.d.ts +21 -0
  67. package/dist/components/atoms/MoneyInput.js +1 -0
  68. package/dist/components/atoms/MoneyInput.mjs +1 -0
  69. package/dist/components/atoms/Paginator.d.mts +21 -0
  70. package/dist/components/atoms/Paginator.d.ts +21 -0
  71. package/dist/components/atoms/Paginator.js +1 -0
  72. package/dist/components/atoms/Paginator.mjs +1 -0
  73. package/dist/components/atoms/PagoTimeAgo.d.mts +8 -0
  74. package/dist/components/atoms/PagoTimeAgo.d.ts +8 -0
  75. package/dist/components/atoms/PagoTimeAgo.js +1 -0
  76. package/dist/components/atoms/PagoTimeAgo.mjs +1 -0
  77. package/dist/components/atoms/PercentageInput.d.mts +19 -0
  78. package/dist/components/atoms/PercentageInput.d.ts +19 -0
  79. package/dist/components/atoms/PercentageInput.js +1 -0
  80. package/dist/components/atoms/PercentageInput.mjs +1 -0
  81. package/dist/components/atoms/ShadowBox.d.mts +14 -0
  82. package/dist/components/atoms/ShadowBox.d.ts +14 -0
  83. package/dist/components/atoms/ShadowBox.js +1 -0
  84. package/dist/components/atoms/ShadowBox.mjs +1 -0
  85. package/dist/components/atoms/ShadowBoxOnMd.d.mts +6 -0
  86. package/dist/components/atoms/ShadowBoxOnMd.d.ts +6 -0
  87. package/dist/components/atoms/ShadowBoxOnMd.js +1 -0
  88. package/dist/components/atoms/ShadowBoxOnMd.mjs +1 -0
  89. package/dist/components/atoms/Sidebar.d.mts +11 -0
  90. package/dist/components/atoms/Sidebar.d.ts +11 -0
  91. package/dist/components/atoms/Sidebar.js +1 -0
  92. package/dist/components/atoms/Sidebar.mjs +1 -0
  93. package/dist/components/molecules/Banner.d.mts +11 -0
  94. package/dist/components/molecules/Banner.d.ts +11 -0
  95. package/dist/components/molecules/Banner.js +1 -0
  96. package/dist/components/molecules/Banner.mjs +1 -0
  97. package/dist/components/ui/accordion.d.mts +19 -0
  98. package/dist/components/ui/accordion.d.ts +19 -0
  99. package/dist/components/ui/accordion.js +1 -0
  100. package/dist/components/ui/accordion.mjs +1 -0
  101. package/dist/components/ui/alert-dialog.d.mts +41 -0
  102. package/dist/components/ui/alert-dialog.d.ts +41 -0
  103. package/dist/components/ui/alert-dialog.js +1 -0
  104. package/dist/components/ui/alert-dialog.mjs +1 -0
  105. package/dist/components/ui/calendar.d.mts +12 -0
  106. package/dist/components/ui/calendar.d.ts +12 -0
  107. package/dist/components/ui/calendar.js +1 -0
  108. package/dist/components/ui/calendar.mjs +1 -0
  109. package/dist/components/ui/card.d.mts +23 -0
  110. package/dist/components/ui/card.d.ts +23 -0
  111. package/dist/components/ui/card.js +1 -0
  112. package/dist/components/ui/card.mjs +1 -0
  113. package/dist/components/ui/chart.d.mts +55 -0
  114. package/dist/components/ui/chart.d.ts +55 -0
  115. package/dist/components/ui/chart.js +7 -0
  116. package/dist/components/ui/chart.mjs +7 -0
  117. package/dist/components/ui/checkbox.d.mts +2 -0
  118. package/dist/components/ui/checkbox.d.ts +2 -0
  119. package/dist/components/ui/checkbox.js +1 -0
  120. package/dist/components/ui/checkbox.mjs +1 -0
  121. package/dist/components/ui/command.d.mts +36 -0
  122. package/dist/components/ui/command.d.ts +36 -0
  123. package/dist/components/ui/command.js +1 -0
  124. package/dist/components/ui/command.mjs +1 -0
  125. package/dist/components/ui/dialog.d.mts +34 -0
  126. package/dist/components/ui/dialog.d.ts +34 -0
  127. package/dist/components/ui/dialog.js +1 -0
  128. package/dist/components/ui/dialog.mjs +1 -0
  129. package/dist/components/ui/dropdown-menu.d.mts +23 -0
  130. package/dist/components/ui/dropdown-menu.d.ts +23 -0
  131. package/dist/components/ui/dropdown-menu.js +1 -0
  132. package/dist/components/ui/dropdown-menu.mjs +1 -0
  133. package/dist/components/ui/form.d.mts +43 -0
  134. package/dist/components/ui/form.d.ts +43 -0
  135. package/dist/components/ui/form.js +1 -0
  136. package/dist/components/ui/form.mjs +1 -0
  137. package/dist/components/ui/input-otp.d.mts +21 -0
  138. package/dist/components/ui/input-otp.d.ts +21 -0
  139. package/dist/components/ui/input-otp.js +1 -0
  140. package/dist/components/ui/input-otp.mjs +1 -0
  141. package/dist/components/ui/label.d.mts +9 -0
  142. package/dist/components/ui/label.d.ts +9 -0
  143. package/dist/components/ui/label.js +1 -0
  144. package/dist/components/ui/label.mjs +1 -0
  145. package/dist/components/ui/popover.d.mts +12 -0
  146. package/dist/components/ui/popover.d.ts +12 -0
  147. package/dist/components/ui/popover.js +1 -0
  148. package/dist/components/ui/popover.mjs +1 -0
  149. package/dist/components/ui/radio-group.d.mts +14 -0
  150. package/dist/components/ui/radio-group.d.ts +14 -0
  151. package/dist/components/ui/radio-group.js +1 -0
  152. package/dist/components/ui/radio-group.mjs +1 -0
  153. package/dist/components/ui/separator.d.mts +10 -0
  154. package/dist/components/ui/separator.d.ts +10 -0
  155. package/dist/components/ui/separator.js +1 -0
  156. package/dist/components/ui/separator.mjs +1 -0
  157. package/dist/components/ui/sheet.d.mts +43 -0
  158. package/dist/components/ui/sheet.d.ts +43 -0
  159. package/dist/components/ui/sheet.js +1 -0
  160. package/dist/components/ui/sheet.mjs +1 -0
  161. package/dist/components/ui/sidebar.d.mts +149 -0
  162. package/dist/components/ui/sidebar.d.ts +149 -0
  163. package/dist/components/ui/sidebar.js +1 -0
  164. package/dist/components/ui/sidebar.mjs +1 -0
  165. package/dist/components/ui/tooltip.d.mts +1 -0
  166. package/dist/components/ui/tooltip.d.ts +1 -0
  167. package/dist/components/ui/tooltip.js +1 -0
  168. package/dist/components/ui/tooltip.mjs +1 -0
  169. package/dist/hooks/theming.d.mts +76 -0
  170. package/dist/hooks/theming.d.ts +76 -0
  171. package/dist/hooks/theming.js +1 -0
  172. package/dist/hooks/theming.mjs +1 -0
  173. package/dist/hooks/use-mobile.d.mts +3 -0
  174. package/dist/hooks/use-mobile.d.ts +3 -0
  175. package/dist/hooks/use-mobile.js +1 -0
  176. package/dist/hooks/use-mobile.mjs +1 -0
  177. package/dist/lib/meterUnit.d.mts +34 -0
  178. package/dist/lib/meterUnit.d.ts +34 -0
  179. package/dist/lib/meterUnit.js +1 -0
  180. package/dist/lib/meterUnit.mjs +1 -0
  181. package/dist/lib/utils.d.mts +5 -0
  182. package/dist/lib/utils.d.ts +5 -0
  183. package/dist/lib/utils.js +1 -0
  184. package/dist/lib/utils.mjs +1 -0
  185. package/eslint.config.mjs +18 -0
  186. package/package.json +74 -0
  187. package/src/components/atoms/Accordion.tsx +56 -0
  188. package/src/components/atoms/Card.tsx +52 -0
  189. package/src/components/atoms/Combobox.tsx +166 -0
  190. package/src/components/atoms/CopyToClipboardInput.tsx +72 -0
  191. package/src/components/atoms/CountryPicker.tsx +81 -0
  192. package/src/components/atoms/CountryStatePicker.tsx +155 -0
  193. package/src/components/atoms/DateTimePicker.tsx +69 -0
  194. package/src/components/atoms/DropdownMenu.tsx +68 -0
  195. package/src/components/atoms/FormattedDateTime.tsx +58 -0
  196. package/src/components/atoms/FormattedInterval.tsx +81 -0
  197. package/src/components/atoms/InputOTP.tsx +7 -0
  198. package/src/components/atoms/MoneyInput.tsx +297 -0
  199. package/src/components/atoms/Paginator.tsx +227 -0
  200. package/src/components/atoms/PagoTimeAgo.tsx +19 -0
  201. package/src/components/atoms/PercentageInput.tsx +97 -0
  202. package/src/components/atoms/ShadowBox.tsx +26 -0
  203. package/src/components/atoms/ShadowBoxOnMd.tsx +20 -0
  204. package/src/components/atoms/Sidebar.tsx +1 -0
  205. package/src/components/molecules/Banner.tsx +42 -0
  206. package/src/components/ui/accordion.tsx +63 -0
  207. package/src/components/ui/alert-dialog.tsx +147 -0
  208. package/src/components/ui/calendar.tsx +81 -0
  209. package/src/components/ui/card.tsx +47 -0
  210. package/src/components/ui/chart.tsx +372 -0
  211. package/src/components/ui/checkbox.tsx +3 -0
  212. package/src/components/ui/command.tsx +133 -0
  213. package/src/components/ui/dialog.tsx +127 -0
  214. package/src/components/ui/dropdown-menu.tsx +74 -0
  215. package/src/components/ui/form.tsx +180 -0
  216. package/src/components/ui/input-otp.tsx +68 -0
  217. package/src/components/ui/label.tsx +25 -0
  218. package/src/components/ui/popover.tsx +34 -0
  219. package/src/components/ui/radio-group.tsx +46 -0
  220. package/src/components/ui/separator.tsx +29 -0
  221. package/src/components/ui/sheet.tsx +149 -0
  222. package/src/components/ui/sidebar.tsx +742 -0
  223. package/src/components/ui/tooltip.tsx +8 -0
  224. package/src/hooks/theming.ts +87 -0
  225. package/src/hooks/use-mobile.ts +19 -0
  226. package/src/lib/meterUnit.ts +52 -0
  227. package/src/lib/utils.ts +6 -0
  228. package/tsconfig.json +15 -0
  229. package/tsup.config.ts +11 -0
@@ -0,0 +1,18 @@
1
+ import { config } from '@pago-sh/eslint-config/react-internal'
2
+
3
+ /** @type {import("eslint").Linter.Config[]} */
4
+ export default [
5
+ {
6
+ ignores: ['node_modules/**', 'dist/**'],
7
+ },
8
+ ...config,
9
+ {
10
+ rules: {
11
+ 'react/prop-types': 'off',
12
+ 'react/no-unknown-property': [
13
+ 'error',
14
+ { ignore: ['cmdk-input-wrapper'] },
15
+ ],
16
+ },
17
+ },
18
+ ]
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@pago-sh/ui",
3
+ "version": "1.0.0",
4
+ "description": "Pago UI Components — This is a private library for the Pago project. You probably shouldn't use it directly in your own projects.",
5
+ "author": "Pago",
6
+ "license": "Apache-2.0",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/pago-sh/pago.git",
10
+ "directory": "clients/packages/ui"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "exports": {
16
+ "./*": {
17
+ "types": "./dist/*.d.ts",
18
+ "import": "./dist/*.mjs",
19
+ "require": "./dist/*.js"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "rm -rf dist && tsup",
24
+ "format": "oxfmt ./src",
25
+ "format:check": "oxfmt --check ./src",
26
+ "lint": "pnpm format:check && eslint --max-warnings 0 .",
27
+ "typecheck": "tsc --noEmit"
28
+ },
29
+ "dependencies": {
30
+ "@pago-sh/currency": "workspace:^",
31
+ "@pago-sh/orbit": "workspace:*",
32
+ "@radix-ui/react-accordion": "^1.2.12",
33
+ "@radix-ui/react-alert-dialog": "^1.1.15",
34
+ "@radix-ui/react-checkbox": "^1.3.3",
35
+ "@radix-ui/react-dialog": "^1.1.15",
36
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
37
+ "@radix-ui/react-label": "^2.1.8",
38
+ "@radix-ui/react-popover": "^1.1.15",
39
+ "@radix-ui/react-radio-group": "^1.3.8",
40
+ "@radix-ui/react-select": "^2.2.6",
41
+ "@radix-ui/react-separator": "^1.1.8",
42
+ "@radix-ui/react-slot": "^1.2.4",
43
+ "@radix-ui/react-switch": "^1.2.6",
44
+ "@radix-ui/react-tabs": "^1.1.13",
45
+ "@radix-ui/react-toast": "^1.2.15",
46
+ "@radix-ui/react-tooltip": "^1.2.8",
47
+ "@tanstack/react-table": "^8.21.3",
48
+ "class-variance-authority": "^0.7.1",
49
+ "cmdk": "^1.1.1",
50
+ "date-fns": "^4.1.0",
51
+ "input-otp": "^1.4.2",
52
+ "lucide-react": "^0.577.0",
53
+ "react-day-picker": "^9.14.0",
54
+ "react-hook-form": "~7.72.1",
55
+ "react-timeago": "^8.3.0",
56
+ "recharts": "^3.8.1",
57
+ "tailwind-merge": "^3.5.0"
58
+ },
59
+ "devDependencies": {
60
+ "@pago-sh/eslint-config": "workspace:*",
61
+ "@pago-sh/typescript-config": "workspace:*",
62
+ "@stripe/stripe-js": "^8.11.0",
63
+ "@types/react": "19.2.14",
64
+ "@types/react-dom": "19.2.3",
65
+ "react": "^19.2.5",
66
+ "react-dom": "^19.2.5",
67
+ "tsup": "^8.5.1",
68
+ "typescript": "5.9.3"
69
+ },
70
+ "peerDependencies": {
71
+ "react": "^18 || ^19",
72
+ "react-dom": "^18 || ^19"
73
+ }
74
+ }
@@ -0,0 +1,56 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+
5
+ import {
6
+ Accordion as ShadAccordion,
7
+ AccordionContent as ShadAccordionContent,
8
+ AccordionItem as ShadAccordionItem,
9
+ AccordionTrigger as ShadAccordionTrigger,
10
+ } from '@/components/ui/accordion'
11
+ import { cn } from '@/lib/utils'
12
+
13
+ const Accordion = ShadAccordion
14
+
15
+ const AccordionItem = ({
16
+ ref,
17
+ className,
18
+ ...props
19
+ }: React.ComponentProps<typeof ShadAccordionItem>) => (
20
+ <ShadAccordionItem
21
+ ref={ref}
22
+ className={cn('rounded-2xl! px-3', className)}
23
+ {...props}
24
+ />
25
+ )
26
+ AccordionItem.displayName = 'AccordionItem'
27
+
28
+ const AccordionTrigger = ({
29
+ ref,
30
+ className,
31
+ children,
32
+ ...props
33
+ }: React.ComponentProps<typeof ShadAccordionTrigger>) => (
34
+ <ShadAccordionTrigger
35
+ ref={ref}
36
+ className={cn('text-sm', className)}
37
+ {...props}
38
+ >
39
+ {children}
40
+ </ShadAccordionTrigger>
41
+ )
42
+ AccordionTrigger.displayName = ShadAccordionTrigger.displayName
43
+
44
+ const AccordionContent = ({
45
+ ref,
46
+ children,
47
+ ...props
48
+ }: React.ComponentProps<typeof ShadAccordionContent>) => (
49
+ <ShadAccordionContent ref={ref} {...props}>
50
+ {children}
51
+ </ShadAccordionContent>
52
+ )
53
+
54
+ AccordionContent.displayName = ShadAccordionContent.displayName
55
+
56
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }
@@ -0,0 +1,52 @@
1
+ import * as React from 'react'
2
+
3
+ import {
4
+ CardContent as CardContentPrimitive,
5
+ CardHeader as CardHeaderPrimitive,
6
+ Card as CardPrimitive,
7
+ } from '@/components/ui/card'
8
+ import { twMerge } from 'tailwind-merge'
9
+
10
+ const Card = ({
11
+ ref,
12
+ className,
13
+ ...props
14
+ }: React.ComponentProps<typeof CardPrimitive>) => (
15
+ <CardPrimitive
16
+ ref={ref}
17
+ className={twMerge(
18
+ 'dark:bg-pago-800 rounded-4xl border-transparent bg-gray-100 text-gray-950 shadow-none dark:border-transparent dark:text-white',
19
+ className,
20
+ )}
21
+ {...props}
22
+ />
23
+ )
24
+ Card.displayName = CardPrimitive.displayName
25
+
26
+ const CardHeader = ({
27
+ ref,
28
+ className,
29
+ ...props
30
+ }: React.ComponentProps<typeof CardHeaderPrimitive>) => (
31
+ <CardHeaderPrimitive
32
+ ref={ref}
33
+ className={twMerge('', className)}
34
+ {...props}
35
+ />
36
+ )
37
+ CardHeader.displayName = CardHeaderPrimitive.displayName
38
+
39
+ const CardContent = ({
40
+ ref,
41
+ className,
42
+ ...props
43
+ }: React.ComponentProps<typeof CardContentPrimitive>) => (
44
+ <CardContentPrimitive
45
+ ref={ref}
46
+ className={twMerge('', className)}
47
+ {...props}
48
+ />
49
+ )
50
+ CardContent.displayName = CardContentPrimitive.displayName
51
+
52
+ export { Card, CardContent, CardHeader }
@@ -0,0 +1,166 @@
1
+ 'use client'
2
+
3
+ import { Check, ChevronsUpDown, Loader2 } from 'lucide-react'
4
+ import * as React from 'react'
5
+
6
+ import { Button } from '@pago-sh/orbit/ui/button'
7
+ import {
8
+ Command,
9
+ CommandEmpty,
10
+ CommandGroup,
11
+ CommandInput,
12
+ CommandItem,
13
+ CommandList,
14
+ } from '@/components/ui/command'
15
+ import {
16
+ Popover,
17
+ PopoverContent,
18
+ PopoverTrigger,
19
+ } from '@/components/ui/popover'
20
+ import { cn } from '@/lib/utils'
21
+
22
+ export interface ComboboxProps<T> {
23
+ // Data
24
+ items: T[]
25
+ value: string | null
26
+ selectedItem: T | null
27
+
28
+ // Callbacks
29
+ onChange: (value: string | null) => void
30
+ onQueryChange: (query: string) => void
31
+ getItemValue: (item: T) => string
32
+ getItemLabel: (item: T) => string
33
+
34
+ // Optional customization
35
+ renderItem?: (item: T) => React.ReactNode
36
+ isLoading?: boolean
37
+
38
+ // Text customization
39
+ placeholder?: string
40
+ searchPlaceholder?: string
41
+ emptyLabel?: string
42
+
43
+ // Styling
44
+ className?: string
45
+ popoverClassName?: string
46
+ popoverAlign?: 'start' | 'center' | 'end'
47
+
48
+ // State
49
+ disabled?: boolean
50
+ }
51
+
52
+ export function Combobox<T>({
53
+ items,
54
+ value,
55
+ selectedItem,
56
+ onChange,
57
+ onQueryChange,
58
+ getItemValue,
59
+ getItemLabel,
60
+ renderItem,
61
+ isLoading = false,
62
+ placeholder = 'Select a value',
63
+ searchPlaceholder = 'Search…',
64
+ emptyLabel = 'No results found',
65
+ className,
66
+ popoverClassName,
67
+ popoverAlign,
68
+ disabled = false,
69
+ }: ComboboxProps<T>) {
70
+ const [open, setOpen] = React.useState(false)
71
+ const [query, setQuery] = React.useState('')
72
+
73
+ const handleQueryChange = React.useCallback(
74
+ (newQuery: string) => {
75
+ setQuery(newQuery)
76
+ onQueryChange(newQuery)
77
+ },
78
+ [onQueryChange],
79
+ )
80
+
81
+ const handleSelect = React.useCallback(
82
+ (itemValue: string) => {
83
+ const newValue = itemValue === value ? null : itemValue
84
+ onChange(newValue)
85
+ setOpen(false)
86
+ },
87
+ [onChange, value],
88
+ )
89
+
90
+ const selectedLabel = React.useMemo(() => {
91
+ if (!value || !selectedItem) return null
92
+ return getItemLabel(selectedItem)
93
+ }, [value, selectedItem, getItemLabel])
94
+
95
+ return (
96
+ <Popover open={open && !disabled} onOpenChange={setOpen}>
97
+ <span className={cn('block w-full', disabled && 'cursor-not-allowed')}>
98
+ <PopoverTrigger asChild>
99
+ <Button
100
+ variant="outline"
101
+ role="combobox"
102
+ aria-expanded={open}
103
+ disabled={disabled}
104
+ className={cn(
105
+ 'dark:bg-pago-800 dark:hover:bg-pago-700 dark:hover:border-pago-700 dark:border-pago-700 flex w-full flex-row justify-between gap-x-2 rounded-lg border border-gray-200 bg-white px-3 shadow-xs transition-colors hover:bg-gray-50 hover:text-black dark:hover:text-white',
106
+ className,
107
+ )}
108
+ >
109
+ {selectedLabel ?? placeholder}
110
+ <ChevronsUpDown className="opacity-50" />
111
+ </Button>
112
+ </PopoverTrigger>
113
+ </span>
114
+ <PopoverContent
115
+ align={popoverAlign}
116
+ className={cn(
117
+ 'w-(--radix-popover-trigger-width) rounded-xl p-0',
118
+ popoverClassName,
119
+ )}
120
+ >
121
+ <Command shouldFilter={false} className="rounded-xl">
122
+ <CommandInput
123
+ placeholder={searchPlaceholder}
124
+ className="h-9 border-0 focus:ring-0 focus:outline-0"
125
+ value={query}
126
+ onValueChange={handleQueryChange}
127
+ />
128
+ <CommandList>
129
+ {isLoading ? (
130
+ <div className="flex items-center justify-center py-6">
131
+ <Loader2 className="h-4 w-4 animate-spin opacity-50" />
132
+ </div>
133
+ ) : items.length === 0 ? (
134
+ <CommandEmpty>{emptyLabel}</CommandEmpty>
135
+ ) : (
136
+ <CommandGroup>
137
+ {items.map((item) => {
138
+ const itemValue = getItemValue(item)
139
+ const itemLabel = getItemLabel(item)
140
+ const isSelected = value === itemValue
141
+
142
+ return (
143
+ <CommandItem
144
+ key={itemValue}
145
+ value={itemValue}
146
+ onSelect={handleSelect}
147
+ className="rounded-md text-black dark:text-white"
148
+ >
149
+ {renderItem ? renderItem(item) : itemLabel}
150
+ <Check
151
+ className={cn(
152
+ 'ml-auto',
153
+ isSelected ? 'opacity-100' : 'opacity-0',
154
+ )}
155
+ />
156
+ </CommandItem>
157
+ )
158
+ })}
159
+ </CommandGroup>
160
+ )}
161
+ </CommandList>
162
+ </Command>
163
+ </PopoverContent>
164
+ </Popover>
165
+ )
166
+ }
@@ -0,0 +1,72 @@
1
+ import { Check } from 'lucide-react'
2
+ import { useState } from 'react'
3
+ import { twMerge } from 'tailwind-merge'
4
+ import { Button } from '@pago-sh/orbit'
5
+ import { Input } from '@pago-sh/orbit'
6
+
7
+ const CopyToClipboardInput = ({
8
+ value,
9
+ onCopy,
10
+ buttonLabel,
11
+ disabled = false,
12
+ className = '',
13
+ variant = 'default',
14
+ }: {
15
+ value: string
16
+ onCopy?: () => void
17
+ buttonLabel?: string
18
+ disabled?: boolean
19
+ className?: string
20
+ variant?: 'default' | 'mono'
21
+ }) => {
22
+ const [isCopied, setIsCopied] = useState(false)
23
+
24
+ const copyToClipboard = () => {
25
+ navigator.clipboard.writeText(value)
26
+
27
+ if (onCopy) {
28
+ onCopy()
29
+ }
30
+
31
+ setIsCopied(true)
32
+
33
+ setTimeout(() => {
34
+ setIsCopied(false)
35
+ }, 2000)
36
+ }
37
+
38
+ return (
39
+ <div
40
+ className={twMerge(
41
+ 'dark:border-pago-700 dark:bg-pago-800 flex w-full flex-row items-center overflow-hidden rounded-xl border bg-white shadow-xs',
42
+ className,
43
+ )}
44
+ >
45
+ <Input
46
+ className={twMerge(
47
+ 'dark:text-pago-400 !focus:border-transparent !focus:ring-transparent !dark:focus:border-transparent !dark:focus:ring-transparent w-full grow border-none bg-transparent text-gray-600 shadow-none! focus-visible:ring-transparent dark:bg-transparent dark:focus-visible:ring-transparent',
48
+ variant === 'mono' ? 'font-mono text-sm' : '',
49
+ )}
50
+ value={value}
51
+ readOnly={true}
52
+ />
53
+ {!disabled && (
54
+ <Button
55
+ className="mr-1 text-xs"
56
+ type="button"
57
+ size="sm"
58
+ variant="ghost"
59
+ onClick={copyToClipboard}
60
+ >
61
+ {isCopied ? (
62
+ <Check className="text-sm" fontSize="inherit" />
63
+ ) : (
64
+ buttonLabel || 'Copy'
65
+ )}
66
+ </Button>
67
+ )}
68
+ </div>
69
+ )
70
+ }
71
+
72
+ export default CopyToClipboardInput
@@ -0,0 +1,81 @@
1
+ 'use client'
2
+
3
+ import { useMemo } from 'react'
4
+
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectItem,
9
+ SelectTrigger,
10
+ SelectValue,
11
+ } from '@pago-sh/orbit'
12
+
13
+ const CountryPicker = ({
14
+ allowedCountries,
15
+ locale,
16
+ value,
17
+ onChange,
18
+ autoComplete,
19
+ disabled,
20
+ className,
21
+ itemClassName,
22
+ contentClassName,
23
+ placeholder = 'Country',
24
+ }: {
25
+ allowedCountries: readonly string[]
26
+ locale?: string
27
+ value?: string
28
+ onChange: (value: string) => void
29
+ autoComplete?: string
30
+ disabled?: boolean
31
+ className?: string
32
+ itemClassName?: string
33
+ contentClassName?: string
34
+ placeholder?: string
35
+ }) => {
36
+ const countryList = useMemo(() => {
37
+ const displayNames = new Intl.DisplayNames(locale ? [locale] : [], {
38
+ type: 'region',
39
+ })
40
+ return allowedCountries
41
+ .map((code) => ({
42
+ code,
43
+ name: displayNames.of(code) ?? code,
44
+ }))
45
+ .sort((a, b) => a.name.localeCompare(b.name, locale))
46
+ }, [allowedCountries, locale])
47
+
48
+ return (
49
+ <Select
50
+ onValueChange={onChange}
51
+ value={value}
52
+ autoComplete={autoComplete}
53
+ disabled={disabled}
54
+ >
55
+ <SelectTrigger className={className}>
56
+ <SelectValue
57
+ placeholder={placeholder}
58
+ // Avoids issues due to browser automatic translation
59
+ // https://github.com/shadcn-ui/ui/issues/852
60
+ translate="no"
61
+ />
62
+ </SelectTrigger>
63
+ <SelectContent className={contentClassName} translate="no">
64
+ {countryList.map(({ code, name }) => (
65
+ <SelectItem
66
+ key={code}
67
+ value={code}
68
+ textValue={name}
69
+ className={itemClassName}
70
+ >
71
+ {/* Wrap in div to workaround an issue with browser automatic translation
72
+ https://github.com/shadcn-ui/ui/issues/852 */}
73
+ <div>{name}</div>
74
+ </SelectItem>
75
+ ))}
76
+ </SelectContent>
77
+ </Select>
78
+ )
79
+ }
80
+
81
+ export default CountryPicker
@@ -0,0 +1,155 @@
1
+ 'use client'
2
+
3
+ import { Input } from '@pago-sh/orbit'
4
+ import {
5
+ Select,
6
+ SelectContent,
7
+ SelectItem,
8
+ SelectTrigger,
9
+ SelectValue,
10
+ } from '@pago-sh/orbit'
11
+
12
+ export const FIXED_STATE_OPTIONS: Record<string, Record<string, string>> = {
13
+ US: {
14
+ 'US-AL': 'Alabama',
15
+ 'US-AK': 'Alaska',
16
+ 'US-AZ': 'Arizona',
17
+ 'US-AR': 'Arkansas',
18
+ 'US-CA': 'California',
19
+ 'US-CO': 'Colorado',
20
+ 'US-CT': 'Connecticut',
21
+ 'US-DE': 'Delaware',
22
+ 'US-FL': 'Florida',
23
+ 'US-GA': 'Georgia',
24
+ 'US-HI': 'Hawaii',
25
+ 'US-ID': 'Idaho',
26
+ 'US-IL': 'Illinois',
27
+ 'US-IN': 'Indiana',
28
+ 'US-IA': 'Iowa',
29
+ 'US-KS': 'Kansas',
30
+ 'US-KY': 'Kentucky',
31
+ 'US-LA': 'Louisiana',
32
+ 'US-ME': 'Maine',
33
+ 'US-MD': 'Maryland',
34
+ 'US-MA': 'Massachusetts',
35
+ 'US-MI': 'Michigan',
36
+ 'US-MN': 'Minnesota',
37
+ 'US-MS': 'Mississippi',
38
+ 'US-MO': 'Missouri',
39
+ 'US-MT': 'Montana',
40
+ 'US-NE': 'Nebraska',
41
+ 'US-NV': 'Nevada',
42
+ 'US-NH': 'New Hampshire',
43
+ 'US-NJ': 'New Jersey',
44
+ 'US-NM': 'New Mexico',
45
+ 'US-NY': 'New York',
46
+ 'US-NC': 'North Carolina',
47
+ 'US-ND': 'North Dakota',
48
+ 'US-OH': 'Ohio',
49
+ 'US-OK': 'Oklahoma',
50
+ 'US-OR': 'Oregon',
51
+ 'US-PA': 'Pennsylvania',
52
+ 'US-RI': 'Rhode Island',
53
+ 'US-SC': 'South Carolina',
54
+ 'US-SD': 'South Dakota',
55
+ 'US-TN': 'Tennessee',
56
+ 'US-TX': 'Texas',
57
+ 'US-UT': 'Utah',
58
+ 'US-VT': 'Vermont',
59
+ 'US-VA': 'Virginia',
60
+ 'US-WA': 'Washington',
61
+ 'US-WV': 'West Virginia',
62
+ 'US-WI': 'Wisconsin',
63
+ 'US-WY': 'Wyoming',
64
+ 'US-DC': 'District of Columbia',
65
+ },
66
+ CA: {
67
+ 'CA-AB': 'Alberta',
68
+ 'CA-BC': 'British Columbia',
69
+ 'CA-MB': 'Manitoba',
70
+ 'CA-NB': 'New Brunswick',
71
+ 'CA-NL': 'Newfoundland and Labrador',
72
+ 'CA-NS': 'Nova Scotia',
73
+ 'CA-NT': 'Northwest Territories',
74
+ 'CA-NU': 'Nunavut',
75
+ 'CA-ON': 'Ontario',
76
+ 'CA-PE': 'Prince Edward Island',
77
+ 'CA-QC': 'Quebec',
78
+ 'CA-SK': 'Saskatchewan',
79
+ 'CA-YT': 'Yukon',
80
+ },
81
+ }
82
+
83
+ export const COUNTRIES_WITH_FIXED_STATE_OPTIONS =
84
+ Object.keys(FIXED_STATE_OPTIONS)
85
+
86
+ const CountryStatePicker = ({
87
+ className,
88
+ value,
89
+ onChange,
90
+ country,
91
+ autoComplete,
92
+ itemClassName,
93
+ contentClassName,
94
+ disabled,
95
+ placeholder = 'State',
96
+ fallbackPlaceholder = 'State / Province',
97
+ }: {
98
+ className?: string
99
+ contentClassName?: string
100
+ itemClassName?: string
101
+ value?: string
102
+ onChange: (value: string) => void
103
+ country?: string
104
+ autoComplete?: string
105
+ disabled?: boolean
106
+ placeholder?: string
107
+ fallbackPlaceholder?: string
108
+ }) => {
109
+ const states = country ? FIXED_STATE_OPTIONS[country] : undefined
110
+ if (states) {
111
+ return (
112
+ <Select
113
+ onValueChange={onChange}
114
+ value={value}
115
+ autoComplete={autoComplete}
116
+ disabled={disabled}
117
+ >
118
+ <SelectTrigger className={className}>
119
+ <SelectValue
120
+ placeholder={placeholder}
121
+ // Avoids issues due to browser automatic translation
122
+ // https://github.com/shadcn-ui/ui/issues/852
123
+ translate="no"
124
+ />
125
+ </SelectTrigger>
126
+ <SelectContent className={contentClassName} translate="no">
127
+ {Object.entries(states).map(([code, name]) => (
128
+ <SelectItem
129
+ key={code}
130
+ value={code}
131
+ textValue={name}
132
+ className={itemClassName}
133
+ >
134
+ {/* Wrap in div to workaround an issue with browser automatic translation
135
+ https://github.com/shadcn-ui/ui/issues/852 */}
136
+ <div>{name}</div>
137
+ </SelectItem>
138
+ ))}
139
+ </SelectContent>
140
+ </Select>
141
+ )
142
+ }
143
+
144
+ return (
145
+ <Input
146
+ type="text"
147
+ placeholder={fallbackPlaceholder}
148
+ value={value}
149
+ onChange={(e) => onChange(e.target.value)}
150
+ disabled={disabled}
151
+ />
152
+ )
153
+ }
154
+
155
+ export default CountryStatePicker