@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,227 @@
1
+ 'use client'
2
+
3
+ import { ChevronLeft, ChevronRight } from 'lucide-react'
4
+ import { useMemo } from 'react'
5
+ import { twMerge } from 'tailwind-merge'
6
+ import { Button } from '@pago-sh/orbit'
7
+
8
+ interface PaginatorProps {
9
+ totalCount: number
10
+ pageSize: number
11
+ currentPage: number
12
+ siblingCount?: number
13
+ onPageChange: (page: number) => void
14
+ className?: string
15
+ currentURL: URLSearchParams
16
+ }
17
+
18
+ const Paginator = ({
19
+ totalCount,
20
+ pageSize,
21
+ currentPage,
22
+ siblingCount = 1,
23
+ onPageChange,
24
+ className,
25
+ currentURL,
26
+ }: PaginatorProps) => {
27
+ const paginationRange = usePagination({
28
+ totalCount,
29
+ currentPage,
30
+ pageSize,
31
+ siblingCount,
32
+ })
33
+
34
+ const buildUrlForPage = (page: number): URLSearchParams => {
35
+ const url = new URLSearchParams(currentURL)
36
+ url.set('page', page.toString())
37
+ return url
38
+ }
39
+
40
+ // If there are less than 2 times in pagination range we shall not render the component
41
+ if (currentPage === 0 || (paginationRange?.length ?? 0) < 2) {
42
+ return null
43
+ }
44
+
45
+ const maybeLastPage = paginationRange?.[paginationRange.length - 1]
46
+ const lastPage = typeof maybeLastPage === 'number' ? maybeLastPage : 1
47
+
48
+ return (
49
+ <div
50
+ className={twMerge(
51
+ 'flex flex-row items-center justify-center gap-x-2',
52
+ className,
53
+ )}
54
+ >
55
+ <a
56
+ // Navigation both with and without JS
57
+ href={`?${buildUrlForPage(currentPage > 1 ? currentPage - 1 : 1)}`}
58
+ onClick={(e) => {
59
+ e.stopPropagation()
60
+ e.preventDefault()
61
+ if (currentPage > 1) {
62
+ onPageChange(currentPage - 1)
63
+ }
64
+ }}
65
+ className={twMerge(currentPage === 1 ? 'cursor-default' : '')}
66
+ >
67
+ <Button
68
+ variant="secondary"
69
+ size="sm"
70
+ asChild
71
+ disabled={currentPage === 1}
72
+ className={twMerge(
73
+ currentPage === 1 ? 'cursor-default opacity-50' : '',
74
+ )}
75
+ >
76
+ <ChevronLeft fontSize="small" />
77
+ </Button>
78
+ </a>
79
+ {paginationRange?.map((pageNumber, idx) => {
80
+ // If the pageItem is a DOT, render the DOTS unicode character
81
+ if (typeof pageNumber !== 'number') {
82
+ return (
83
+ <div className="dark:text-pago-400 text-gray-400" key={idx}>
84
+ &#8230;
85
+ </div>
86
+ )
87
+ }
88
+
89
+ // Render page pills
90
+ return (
91
+ <a
92
+ href={`?${buildUrlForPage(pageNumber)}`}
93
+ key={idx}
94
+ onClick={(e) => {
95
+ e.stopPropagation()
96
+ e.preventDefault()
97
+ if (pageNumber !== currentPage) onPageChange(pageNumber)
98
+ }}
99
+ >
100
+ <Button
101
+ asChild
102
+ variant={pageNumber === currentPage ? 'default' : 'secondary'}
103
+ size="sm"
104
+ >
105
+ {pageNumber}
106
+ </Button>
107
+ </a>
108
+ )
109
+ })}
110
+
111
+ <a
112
+ href={`?${buildUrlForPage(lastPage)}`}
113
+ onClick={(e) => {
114
+ e.stopPropagation()
115
+ e.preventDefault()
116
+ if (currentPage < lastPage) {
117
+ onPageChange(currentPage + 1)
118
+ }
119
+ }}
120
+ className={twMerge(currentPage >= lastPage ? 'cursor-default' : '')}
121
+ >
122
+ <Button
123
+ variant="secondary"
124
+ asChild
125
+ size="sm"
126
+ disabled={currentPage >= lastPage}
127
+ className={twMerge(
128
+ currentPage >= lastPage ? 'cursor-default opacity-50' : '',
129
+ )}
130
+ >
131
+ <ChevronRight fontSize="small" />
132
+ </Button>
133
+ </a>
134
+ </div>
135
+ )
136
+ }
137
+
138
+ export default Paginator
139
+
140
+ const range = (start: number, end: number) => {
141
+ const length = end - start + 1
142
+ /*
143
+ Create an array of certain length and set the elements within it from
144
+ start value to end value.
145
+ */
146
+ return Array.from({ length }, (_, idx) => idx + start)
147
+ }
148
+
149
+ const DOTS = Symbol('DOTS')
150
+
151
+ export const usePagination = ({
152
+ totalCount,
153
+ pageSize,
154
+ siblingCount = 1,
155
+ currentPage,
156
+ }: {
157
+ totalCount: number
158
+ pageSize: number
159
+ siblingCount?: number
160
+ currentPage: number
161
+ }) => {
162
+ const paginationRange = useMemo(() => {
163
+ const totalPageCount = Math.ceil(totalCount / pageSize)
164
+
165
+ // Pages count is determined as siblingCount + firstPage + lastPage + currentPage + 2*DOTS
166
+ const totalPageNumbers = siblingCount + 5
167
+
168
+ /*
169
+ Case 1:
170
+ If the number of pages is less than the page numbers we want to show in our
171
+ paginationComponent, we return the range [1..totalPageCount]
172
+ */
173
+ if (totalPageNumbers >= totalPageCount) {
174
+ return range(1, totalPageCount)
175
+ }
176
+
177
+ /*
178
+ Calculate left and right sibling index and make sure they are within range 1 and totalPageCount
179
+ */
180
+ const leftSiblingIndex = Math.max(currentPage - siblingCount, 1)
181
+ const rightSiblingIndex = Math.min(
182
+ currentPage + siblingCount,
183
+ totalPageCount,
184
+ )
185
+
186
+ /*
187
+ We do not show dots just when there is just one page number to be inserted between the extremes of sibling and the page limits i.e 1 and totalPageCount. Hence we are using leftSiblingIndex > 2 and rightSiblingIndex < totalPageCount - 2
188
+ */
189
+ const shouldShowLeftDots = leftSiblingIndex > 2
190
+ const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2
191
+
192
+ const firstPageIndex = 1
193
+ const lastPageIndex = totalPageCount
194
+
195
+ /*
196
+ Case 2: No left dots to show, but rights dots to be shown
197
+ */
198
+ if (!shouldShowLeftDots && shouldShowRightDots) {
199
+ const leftItemCount = 3 + 2 * siblingCount
200
+ const leftRange = range(1, leftItemCount)
201
+
202
+ return [...leftRange, DOTS, totalPageCount]
203
+ }
204
+
205
+ /*
206
+ Case 3: No right dots to show, but left dots to be shown
207
+ */
208
+ if (shouldShowLeftDots && !shouldShowRightDots) {
209
+ const rightItemCount = 3 + 2 * siblingCount
210
+ const rightRange = range(
211
+ totalPageCount - rightItemCount + 1,
212
+ totalPageCount,
213
+ )
214
+ return [firstPageIndex, DOTS, ...rightRange]
215
+ }
216
+
217
+ /*
218
+ Case 4: Both left and right dots to be shown
219
+ */
220
+ if (shouldShowLeftDots && shouldShowRightDots) {
221
+ const middleRange = range(leftSiblingIndex, rightSiblingIndex)
222
+ return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex]
223
+ }
224
+ }, [totalCount, pageSize, siblingCount, currentPage])
225
+
226
+ return paginationRange
227
+ }
@@ -0,0 +1,19 @@
1
+ import TimeAgo from 'react-timeago'
2
+
3
+ const PagoTimeAgo = (props: { date: Date; suffix?: string }) => {
4
+ return (
5
+ <TimeAgo
6
+ date={props.date}
7
+ formatter={(value: number, unit: string, suffix: string) => {
8
+ if (unit === 'second') {
9
+ return 'just now'
10
+ }
11
+ return `${value} ${unit}${value !== 1 ? 's' : ''} ${
12
+ props.suffix ?? suffix
13
+ }`
14
+ }}
15
+ />
16
+ )
17
+ }
18
+
19
+ export default PagoTimeAgo
@@ -0,0 +1,97 @@
1
+ import { Percent } from 'lucide-react'
2
+ import {
3
+ ChangeEvent,
4
+ FocusEvent,
5
+ InputEvent,
6
+ useCallback,
7
+ useState,
8
+ } from 'react'
9
+ import { twMerge } from 'tailwind-merge'
10
+ import { Input } from '@pago-sh/orbit'
11
+
12
+ interface Props {
13
+ name: string
14
+ placeholder: number
15
+ id?: string
16
+ onChange?: (value: number) => void
17
+ onBlur?: (e: ChangeEvent<HTMLInputElement>) => void
18
+ onFocus?: (e: FocusEvent<HTMLInputElement>) => void
19
+ value?: number
20
+ className?: string
21
+ disabled?: boolean
22
+ preSlot?: React.ReactNode
23
+ postSlot?: React.ReactNode
24
+ }
25
+
26
+ const getPercentageBasisPoints = (value: string): number => {
27
+ let newAmount = Number.parseFloat(value)
28
+ if (isNaN(newAmount)) {
29
+ newAmount = 0
30
+ }
31
+ return Math.round(newAmount * 100)
32
+ }
33
+
34
+ const PercentageInput = (props: Props) => {
35
+ const {
36
+ id,
37
+ name,
38
+ value,
39
+ placeholder,
40
+ preSlot,
41
+ postSlot,
42
+ onChange: _onChange,
43
+ onBlur,
44
+ onFocus,
45
+ disabled,
46
+ } = props
47
+ const [internalValue, setInternalValue] = useState<string | undefined>(
48
+ value ? (value / 100).toFixed(2) : undefined,
49
+ )
50
+
51
+ const onChange = useCallback(
52
+ (e: ChangeEvent<HTMLInputElement>) => {
53
+ if (_onChange) {
54
+ _onChange(getPercentageBasisPoints(e.target.value))
55
+ }
56
+ setInternalValue(e.target.value)
57
+ },
58
+ [_onChange],
59
+ )
60
+
61
+ const onInput = (e: InputEvent<HTMLInputElement>) => {
62
+ const value = e.currentTarget.value
63
+ const regex = /^\d+([.,]\d{0,2})?$/
64
+ if (!regex.test(value)) {
65
+ e.currentTarget.value = Number.parseFloat(value).toFixed(2)
66
+ }
67
+ }
68
+
69
+ return (
70
+ <Input
71
+ type="number"
72
+ step={0.01}
73
+ min={0.01}
74
+ max={100}
75
+ id={id}
76
+ name={name}
77
+ className={twMerge(
78
+ 'dark:placeholder:text-pago-500 block w-full px-4 text-base placeholder:text-gray-400',
79
+ props.className ?? '',
80
+ )}
81
+ value={internalValue}
82
+ onChange={onChange}
83
+ onInput={onInput}
84
+ placeholder={placeholder ? `${placeholder / 100}` : undefined}
85
+ postSlot={postSlot ? postSlot : <Percent className="h-4 w-4" />}
86
+ preSlot={preSlot}
87
+ onBlur={onBlur}
88
+ onFocus={onFocus}
89
+ onWheel={(e) => {
90
+ ;(e.target as HTMLInputElement).blur()
91
+ }}
92
+ disabled={disabled}
93
+ />
94
+ )
95
+ }
96
+
97
+ export default PercentageInput
@@ -0,0 +1,26 @@
1
+ import { PropsWithChildren } from 'react'
2
+ import { twMerge } from 'tailwind-merge'
3
+ import ShadowBoxOnMd from './ShadowBoxOnMd'
4
+
5
+ const ShadowBox = ({
6
+ ref,
7
+ ...props
8
+ }: PropsWithChildren<{ className?: string }> & {
9
+ ref?: React.RefObject<HTMLDivElement>
10
+ }) => (
11
+ <div
12
+ ref={ref}
13
+ className={twMerge(
14
+ 'dark:bg-pago-900 dark:border-pago-700 w-full rounded-xl border border-transparent bg-gray-50 p-8 lg:rounded-4xl',
15
+ props.className,
16
+ )}
17
+ >
18
+ {props.children}
19
+ </div>
20
+ )
21
+
22
+ ShadowBox.displayName = 'ShadowBox'
23
+
24
+ export default ShadowBox
25
+
26
+ export { ShadowBoxOnMd }
@@ -0,0 +1,20 @@
1
+ import { DetailedHTMLProps } from 'react'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ const ShadowBoxOnMd = ({
5
+ className,
6
+ children,
7
+ ...props
8
+ }: DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>) => (
9
+ <div
10
+ className={twMerge(
11
+ 'md:dark:bg-pago-900 dark:border-pago-700 w-full md:rounded-xl md:border md:border-transparent md:bg-gray-50 md:p-8 lg:rounded-4xl',
12
+ className,
13
+ )}
14
+ {...props}
15
+ >
16
+ {children}
17
+ </div>
18
+ )
19
+
20
+ export default ShadowBoxOnMd
@@ -0,0 +1 @@
1
+ export * from '@/components/ui/sidebar'
@@ -0,0 +1,42 @@
1
+ import React from 'react'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ type Color = 'default' | 'muted' | 'red' | 'green' | 'blue'
5
+
6
+ const Banner = ({
7
+ children,
8
+ right,
9
+ color,
10
+ }: {
11
+ children: React.ReactNode
12
+ right?: React.ReactNode
13
+ color: Color
14
+ }) => {
15
+ return (
16
+ <div
17
+ className={twMerge(
18
+ 'flex items-center justify-between gap-2 rounded-lg px-3 py-2 text-sm',
19
+ color === 'default'
20
+ ? 'dark:bg-pago-800 dark:ring-pago-700 bg-white ring-1 ring-gray-100'
21
+ : '',
22
+ color === 'muted'
23
+ ? 'dark:bg-pago-800 dark:border-pago-700 border bg-gray-100 text-gray-500'
24
+ : '',
25
+ color === 'red'
26
+ ? 'border bg-red-100 text-red-600 dark:border-red-900 dark:bg-red-950/50 dark:text-red-600'
27
+ : '',
28
+ color === 'green'
29
+ ? 'border bg-green-100 text-green-600 dark:border-green-800 dark:bg-green-900 dark:text-green-200'
30
+ : '',
31
+ color === 'blue'
32
+ ? 'border border-blue-100 bg-blue-50 text-blue-500 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-300'
33
+ : '',
34
+ )}
35
+ >
36
+ <div className="flex flex-1 items-center gap-2">{children}</div>
37
+ {right && <div>{right}</div>}
38
+ </div>
39
+ )
40
+ }
41
+
42
+ export default Banner
@@ -0,0 +1,63 @@
1
+ 'use client'
2
+
3
+ import * as AccordionPrimitive from '@radix-ui/react-accordion'
4
+ import { ChevronDown } from 'lucide-react'
5
+ import * as React from 'react'
6
+
7
+ import { cn } from '@/lib/utils'
8
+
9
+ const Accordion = AccordionPrimitive.Root
10
+
11
+ const AccordionItem = ({
12
+ ref,
13
+ className,
14
+ ...props
15
+ }: React.ComponentProps<typeof AccordionPrimitive.Item>) => (
16
+ <AccordionPrimitive.Item
17
+ ref={ref}
18
+ className={cn('border-b', className)}
19
+ {...props}
20
+ />
21
+ )
22
+ AccordionItem.displayName = 'AccordionItem'
23
+
24
+ const AccordionTrigger = ({
25
+ ref,
26
+ className,
27
+ children,
28
+ ...props
29
+ }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) => (
30
+ <AccordionPrimitive.Header className="flex">
31
+ <AccordionPrimitive.Trigger
32
+ ref={ref}
33
+ className={cn(
34
+ 'flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
35
+ className,
36
+ )}
37
+ {...props}
38
+ >
39
+ {children}
40
+ <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
41
+ </AccordionPrimitive.Trigger>
42
+ </AccordionPrimitive.Header>
43
+ )
44
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
45
+
46
+ const AccordionContent = ({
47
+ ref,
48
+ className,
49
+ children,
50
+ ...props
51
+ }: React.ComponentProps<typeof AccordionPrimitive.Content>) => (
52
+ <AccordionPrimitive.Content
53
+ ref={ref}
54
+ className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm transition-all"
55
+ {...props}
56
+ >
57
+ <div className={cn('pt-0 pb-4', className)}>{children}</div>
58
+ </AccordionPrimitive.Content>
59
+ )
60
+
61
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName
62
+
63
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }
@@ -0,0 +1,147 @@
1
+ 'use client'
2
+
3
+ import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
4
+ import * as React from 'react'
5
+
6
+ import { buttonVariants } from '@pago-sh/orbit/ui/button'
7
+ import { cn } from '@/lib/utils'
8
+
9
+ const AlertDialog = AlertDialogPrimitive.Root
10
+
11
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12
+
13
+ const AlertDialogPortal = AlertDialogPrimitive.Portal
14
+
15
+ const AlertDialogOverlay = ({
16
+ ref,
17
+ className,
18
+ ...props
19
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) => (
20
+ <AlertDialogPrimitive.Overlay
21
+ className={cn(
22
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
23
+ className,
24
+ )}
25
+ {...props}
26
+ ref={ref}
27
+ />
28
+ )
29
+ AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
30
+
31
+ const AlertDialogContent = ({
32
+ ref,
33
+ className,
34
+ ...props
35
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) => (
36
+ <AlertDialogPortal>
37
+ <AlertDialogOverlay />
38
+ <AlertDialogPrimitive.Content
39
+ ref={ref}
40
+ className={cn(
41
+ 'bg-background 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 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed top-[50%] left-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
42
+ className,
43
+ )}
44
+ {...props}
45
+ />
46
+ </AlertDialogPortal>
47
+ )
48
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
49
+
50
+ const AlertDialogHeader = ({
51
+ className,
52
+ ...props
53
+ }: React.HTMLAttributes<HTMLDivElement>) => (
54
+ <div
55
+ className={cn(
56
+ 'flex flex-col space-y-2 text-center sm:text-left',
57
+ className,
58
+ )}
59
+ {...props}
60
+ />
61
+ )
62
+ AlertDialogHeader.displayName = 'AlertDialogHeader'
63
+
64
+ const AlertDialogFooter = ({
65
+ className,
66
+ ...props
67
+ }: React.HTMLAttributes<HTMLDivElement>) => (
68
+ <div
69
+ className={cn(
70
+ 'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
71
+ className,
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ AlertDialogFooter.displayName = 'AlertDialogFooter'
77
+
78
+ const AlertDialogTitle = ({
79
+ ref,
80
+ className,
81
+ ...props
82
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) => (
83
+ <AlertDialogPrimitive.Title
84
+ ref={ref}
85
+ className={cn('text-lg font-semibold', className)}
86
+ {...props}
87
+ />
88
+ )
89
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
90
+
91
+ const AlertDialogDescription = ({
92
+ ref,
93
+ className,
94
+ ...props
95
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) => (
96
+ <AlertDialogPrimitive.Description
97
+ ref={ref}
98
+ className={cn('text-muted-foreground text-sm', className)}
99
+ {...props}
100
+ />
101
+ )
102
+ AlertDialogDescription.displayName =
103
+ AlertDialogPrimitive.Description.displayName
104
+
105
+ const AlertDialogAction = ({
106
+ ref,
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) => (
110
+ <AlertDialogPrimitive.Action
111
+ ref={ref}
112
+ className={cn(buttonVariants(), className)}
113
+ {...props}
114
+ />
115
+ )
116
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
117
+
118
+ const AlertDialogCancel = ({
119
+ ref,
120
+ className,
121
+ ...props
122
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) => (
123
+ <AlertDialogPrimitive.Cancel
124
+ ref={ref}
125
+ className={cn(
126
+ buttonVariants({ variant: 'outline' }),
127
+ 'mt-2 sm:mt-0',
128
+ className,
129
+ )}
130
+ {...props}
131
+ />
132
+ )
133
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
134
+
135
+ export {
136
+ AlertDialog,
137
+ AlertDialogAction,
138
+ AlertDialogCancel,
139
+ AlertDialogContent,
140
+ AlertDialogDescription,
141
+ AlertDialogFooter,
142
+ AlertDialogHeader,
143
+ AlertDialogOverlay,
144
+ AlertDialogPortal,
145
+ AlertDialogTitle,
146
+ AlertDialogTrigger,
147
+ }