@peak-ai/canvas 1.4.21 → 1.4.22

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 (213) hide show
  1. package/.babelrc +14 -0
  2. package/.eslintcache +1 -0
  3. package/.eslintignore +5 -0
  4. package/.eslintrc.js +29 -0
  5. package/{GrapesjsCanvas.js → dist/GrapesjsCanvas.js} +3 -2
  6. package/dist/GrapesjsCanvas.js.map +1 -0
  7. package/dist/package.json +62 -0
  8. package/{plugins → dist/plugins}/helpers/render-components.js +1 -1
  9. package/dist/plugins/helpers/render-components.js.map +1 -0
  10. package/dist/shadcn/components/ui/error-wrapper.js +2 -0
  11. package/dist/shadcn/components/ui/error-wrapper.js.map +1 -0
  12. package/package.json +45 -7
  13. package/scripts/build.ts +120 -0
  14. package/src/GrapesjsCanvas.tsx +494 -0
  15. package/src/constants/index.ts +25 -0
  16. package/src/declaration.d.ts +1 -0
  17. package/src/helpers/compiled-table.css +2429 -0
  18. package/src/helpers/css.ts +2667 -0
  19. package/src/helpers/date-picker.ts +807 -0
  20. package/src/helpers/filter-placeholder.ts +18 -0
  21. package/src/helpers/index.ts +13 -0
  22. package/src/helpers/merge-json.ts +106 -0
  23. package/src/index.styles.ts +58 -0
  24. package/src/index.ts +9 -0
  25. package/src/plugins/grapejs-plugin.tsx +196 -0
  26. package/src/plugins/helpers/custom-modal.tsx +123 -0
  27. package/src/plugins/helpers/data-table.tsx +300 -0
  28. package/src/plugins/helpers/extra.tsx +164 -0
  29. package/src/plugins/helpers/query-cache-context.tsx +154 -0
  30. package/src/plugins/helpers/query-cache-singleton.ts +176 -0
  31. package/src/plugins/helpers/query-cache-utils.ts +226 -0
  32. package/src/plugins/helpers/query-details-modal.tsx +400 -0
  33. package/src/plugins/helpers/query-heading-formatter.ts +24 -0
  34. package/src/plugins/helpers/query-loading-modal.tsx +94 -0
  35. package/src/plugins/helpers/render-components.tsx +1450 -0
  36. package/src/plugins/helpers/styled-info-button.tsx +504 -0
  37. package/src/public/canvas.css +42 -0
  38. package/src/public/components-css/table/table-output.css +2436 -0
  39. package/src/public/components-css/table/table.css +30 -0
  40. package/src/public/output.css +2465 -0
  41. package/src/public/table.css +135 -0
  42. package/src/shadcn/components/icons/AiAvatarIcon.tsx +47 -0
  43. package/src/shadcn/components/icons/Co_driver Expanding button copy.svg +21 -0
  44. package/src/shadcn/components/icons/ai-avatar.svg +7 -0
  45. package/src/shadcn/components/icons/thinking.gif +0 -0
  46. package/src/shadcn/components/ui/button.tsx +132 -0
  47. package/src/shadcn/components/ui/card.tsx +92 -0
  48. package/src/shadcn/components/ui/chart.tsx +324 -0
  49. package/src/shadcn/components/ui/checkbox.tsx +27 -0
  50. package/src/shadcn/components/ui/component-wrapper.tsx +61 -0
  51. package/src/shadcn/components/ui/date-filter.tsx +816 -0
  52. package/src/shadcn/components/ui/error-container.tsx +125 -0
  53. package/src/shadcn/components/ui/error-wrapper.tsx +99 -0
  54. package/src/shadcn/components/ui/filter.tsx +368 -0
  55. package/src/shadcn/components/ui/hover-card.tsx +36 -0
  56. package/src/shadcn/components/ui/input.tsx +20 -0
  57. package/src/shadcn/components/ui/label.tsx +24 -0
  58. package/src/shadcn/components/ui/pagination.tsx +213 -0
  59. package/src/shadcn/components/ui/scroll-area.tsx +59 -0
  60. package/src/shadcn/components/ui/search.tsx +150 -0
  61. package/src/shadcn/components/ui/separator.tsx +26 -0
  62. package/src/shadcn/components/ui/skeleton.tsx +69 -0
  63. package/src/shadcn/components/ui/table.tsx +196 -0
  64. package/src/shadcn/components/ui/tabs.tsx +55 -0
  65. package/src/shadcn/components/ui/textarea.tsx +18 -0
  66. package/src/shadcn/components/ui/tooltip.tsx +87 -0
  67. package/src/shadcn/utils.ts +6 -0
  68. package/src/types/grapesjs-tailwind.d.ts +61 -0
  69. package/src/types/images.d.ts +1 -0
  70. package/tailwind.config.js +5 -0
  71. package/tooling/tailwind-compiler/index.js +99 -0
  72. package/tooling/tailwind-compiler/package.json +11 -0
  73. package/tooling/tailwind-compiler/yarn.lock +123 -0
  74. package/tsconfig.build.json +15 -0
  75. package/tsconfig.json +8 -0
  76. package/GrapesjsCanvas.js.map +0 -1
  77. package/plugins/helpers/render-components.js.map +0 -1
  78. package/shadcn/components/ui/error-wrapper.js +0 -2
  79. package/shadcn/components/ui/error-wrapper.js.map +0 -1
  80. /package/{GrapesjsCanvas.d.ts → dist/GrapesjsCanvas.d.ts} +0 -0
  81. /package/{constants → dist/constants}/index.d.ts +0 -0
  82. /package/{constants → dist/constants}/index.js +0 -0
  83. /package/{constants → dist/constants}/index.js.map +0 -0
  84. /package/{declaration.d.js → dist/declaration.d.js} +0 -0
  85. /package/{declaration.d.js.map → dist/declaration.d.js.map} +0 -0
  86. /package/{helpers → dist/helpers}/compiled-table.css +0 -0
  87. /package/{helpers → dist/helpers}/css.d.ts +0 -0
  88. /package/{helpers → dist/helpers}/css.js +0 -0
  89. /package/{helpers → dist/helpers}/css.js.map +0 -0
  90. /package/{helpers → dist/helpers}/date-picker.d.ts +0 -0
  91. /package/{helpers → dist/helpers}/date-picker.js +0 -0
  92. /package/{helpers → dist/helpers}/date-picker.js.map +0 -0
  93. /package/{helpers → dist/helpers}/filter-placeholder.d.ts +0 -0
  94. /package/{helpers → dist/helpers}/filter-placeholder.js +0 -0
  95. /package/{helpers → dist/helpers}/filter-placeholder.js.map +0 -0
  96. /package/{helpers → dist/helpers}/index.d.ts +0 -0
  97. /package/{helpers → dist/helpers}/index.js +0 -0
  98. /package/{helpers → dist/helpers}/index.js.map +0 -0
  99. /package/{helpers → dist/helpers}/merge-json.d.ts +0 -0
  100. /package/{helpers → dist/helpers}/merge-json.js +0 -0
  101. /package/{helpers → dist/helpers}/merge-json.js.map +0 -0
  102. /package/{index.d.ts → dist/index.d.ts} +0 -0
  103. /package/{index.js → dist/index.js} +0 -0
  104. /package/{index.js.map → dist/index.js.map} +0 -0
  105. /package/{index.styles.d.ts → dist/index.styles.d.ts} +0 -0
  106. /package/{index.styles.js → dist/index.styles.js} +0 -0
  107. /package/{index.styles.js.map → dist/index.styles.js.map} +0 -0
  108. /package/{plugins → dist/plugins}/grapejs-plugin.d.ts +0 -0
  109. /package/{plugins → dist/plugins}/grapejs-plugin.js +0 -0
  110. /package/{plugins → dist/plugins}/grapejs-plugin.js.map +0 -0
  111. /package/{plugins → dist/plugins}/helpers/custom-modal.d.ts +0 -0
  112. /package/{plugins → dist/plugins}/helpers/custom-modal.js +0 -0
  113. /package/{plugins → dist/plugins}/helpers/custom-modal.js.map +0 -0
  114. /package/{plugins → dist/plugins}/helpers/data-table.d.ts +0 -0
  115. /package/{plugins → dist/plugins}/helpers/data-table.js +0 -0
  116. /package/{plugins → dist/plugins}/helpers/data-table.js.map +0 -0
  117. /package/{plugins → dist/plugins}/helpers/extra.d.ts +0 -0
  118. /package/{plugins → dist/plugins}/helpers/extra.js +0 -0
  119. /package/{plugins → dist/plugins}/helpers/extra.js.map +0 -0
  120. /package/{plugins → dist/plugins}/helpers/query-cache-context.d.ts +0 -0
  121. /package/{plugins → dist/plugins}/helpers/query-cache-context.js +0 -0
  122. /package/{plugins → dist/plugins}/helpers/query-cache-context.js.map +0 -0
  123. /package/{plugins → dist/plugins}/helpers/query-cache-singleton.d.ts +0 -0
  124. /package/{plugins → dist/plugins}/helpers/query-cache-singleton.js +0 -0
  125. /package/{plugins → dist/plugins}/helpers/query-cache-singleton.js.map +0 -0
  126. /package/{plugins → dist/plugins}/helpers/query-cache-utils.d.ts +0 -0
  127. /package/{plugins → dist/plugins}/helpers/query-cache-utils.js +0 -0
  128. /package/{plugins → dist/plugins}/helpers/query-cache-utils.js.map +0 -0
  129. /package/{plugins → dist/plugins}/helpers/query-details-modal.d.ts +0 -0
  130. /package/{plugins → dist/plugins}/helpers/query-details-modal.js +0 -0
  131. /package/{plugins → dist/plugins}/helpers/query-details-modal.js.map +0 -0
  132. /package/{plugins → dist/plugins}/helpers/query-heading-formatter.d.ts +0 -0
  133. /package/{plugins → dist/plugins}/helpers/query-heading-formatter.js +0 -0
  134. /package/{plugins → dist/plugins}/helpers/query-heading-formatter.js.map +0 -0
  135. /package/{plugins → dist/plugins}/helpers/query-loading-modal.d.ts +0 -0
  136. /package/{plugins → dist/plugins}/helpers/query-loading-modal.js +0 -0
  137. /package/{plugins → dist/plugins}/helpers/query-loading-modal.js.map +0 -0
  138. /package/{plugins → dist/plugins}/helpers/render-components.d.ts +0 -0
  139. /package/{plugins → dist/plugins}/helpers/styled-info-button.d.ts +0 -0
  140. /package/{plugins → dist/plugins}/helpers/styled-info-button.js +0 -0
  141. /package/{plugins → dist/plugins}/helpers/styled-info-button.js.map +0 -0
  142. /package/{shadcn → dist/shadcn}/components/icons/AiAvatarIcon.d.ts +0 -0
  143. /package/{shadcn → dist/shadcn}/components/icons/AiAvatarIcon.js +0 -0
  144. /package/{shadcn → dist/shadcn}/components/icons/AiAvatarIcon.js.map +0 -0
  145. /package/{shadcn → dist/shadcn}/components/icons/thinking.gif +0 -0
  146. /package/{shadcn → dist/shadcn}/components/ui/button.d.ts +0 -0
  147. /package/{shadcn → dist/shadcn}/components/ui/button.js +0 -0
  148. /package/{shadcn → dist/shadcn}/components/ui/button.js.map +0 -0
  149. /package/{shadcn → dist/shadcn}/components/ui/card.d.ts +0 -0
  150. /package/{shadcn → dist/shadcn}/components/ui/card.js +0 -0
  151. /package/{shadcn → dist/shadcn}/components/ui/card.js.map +0 -0
  152. /package/{shadcn → dist/shadcn}/components/ui/chart.d.ts +0 -0
  153. /package/{shadcn → dist/shadcn}/components/ui/chart.js +0 -0
  154. /package/{shadcn → dist/shadcn}/components/ui/chart.js.map +0 -0
  155. /package/{shadcn → dist/shadcn}/components/ui/checkbox.d.ts +0 -0
  156. /package/{shadcn → dist/shadcn}/components/ui/checkbox.js +0 -0
  157. /package/{shadcn → dist/shadcn}/components/ui/checkbox.js.map +0 -0
  158. /package/{shadcn → dist/shadcn}/components/ui/component-wrapper.d.ts +0 -0
  159. /package/{shadcn → dist/shadcn}/components/ui/component-wrapper.js +0 -0
  160. /package/{shadcn → dist/shadcn}/components/ui/component-wrapper.js.map +0 -0
  161. /package/{shadcn → dist/shadcn}/components/ui/date-filter.d.ts +0 -0
  162. /package/{shadcn → dist/shadcn}/components/ui/date-filter.js +0 -0
  163. /package/{shadcn → dist/shadcn}/components/ui/date-filter.js.map +0 -0
  164. /package/{shadcn → dist/shadcn}/components/ui/error-container.d.ts +0 -0
  165. /package/{shadcn → dist/shadcn}/components/ui/error-container.js +0 -0
  166. /package/{shadcn → dist/shadcn}/components/ui/error-container.js.map +0 -0
  167. /package/{shadcn → dist/shadcn}/components/ui/error-wrapper.d.ts +0 -0
  168. /package/{shadcn → dist/shadcn}/components/ui/filter.d.ts +0 -0
  169. /package/{shadcn → dist/shadcn}/components/ui/filter.js +0 -0
  170. /package/{shadcn → dist/shadcn}/components/ui/filter.js.map +0 -0
  171. /package/{shadcn → dist/shadcn}/components/ui/hover-card.d.ts +0 -0
  172. /package/{shadcn → dist/shadcn}/components/ui/hover-card.js +0 -0
  173. /package/{shadcn → dist/shadcn}/components/ui/hover-card.js.map +0 -0
  174. /package/{shadcn → dist/shadcn}/components/ui/input.d.ts +0 -0
  175. /package/{shadcn → dist/shadcn}/components/ui/input.js +0 -0
  176. /package/{shadcn → dist/shadcn}/components/ui/input.js.map +0 -0
  177. /package/{shadcn → dist/shadcn}/components/ui/label.d.ts +0 -0
  178. /package/{shadcn → dist/shadcn}/components/ui/label.js +0 -0
  179. /package/{shadcn → dist/shadcn}/components/ui/label.js.map +0 -0
  180. /package/{shadcn → dist/shadcn}/components/ui/pagination.d.ts +0 -0
  181. /package/{shadcn → dist/shadcn}/components/ui/pagination.js +0 -0
  182. /package/{shadcn → dist/shadcn}/components/ui/pagination.js.map +0 -0
  183. /package/{shadcn → dist/shadcn}/components/ui/scroll-area.d.ts +0 -0
  184. /package/{shadcn → dist/shadcn}/components/ui/scroll-area.js +0 -0
  185. /package/{shadcn → dist/shadcn}/components/ui/scroll-area.js.map +0 -0
  186. /package/{shadcn → dist/shadcn}/components/ui/search.d.ts +0 -0
  187. /package/{shadcn → dist/shadcn}/components/ui/search.js +0 -0
  188. /package/{shadcn → dist/shadcn}/components/ui/search.js.map +0 -0
  189. /package/{shadcn → dist/shadcn}/components/ui/separator.d.ts +0 -0
  190. /package/{shadcn → dist/shadcn}/components/ui/separator.js +0 -0
  191. /package/{shadcn → dist/shadcn}/components/ui/separator.js.map +0 -0
  192. /package/{shadcn → dist/shadcn}/components/ui/skeleton.d.ts +0 -0
  193. /package/{shadcn → dist/shadcn}/components/ui/skeleton.js +0 -0
  194. /package/{shadcn → dist/shadcn}/components/ui/skeleton.js.map +0 -0
  195. /package/{shadcn → dist/shadcn}/components/ui/table.d.ts +0 -0
  196. /package/{shadcn → dist/shadcn}/components/ui/table.js +0 -0
  197. /package/{shadcn → dist/shadcn}/components/ui/table.js.map +0 -0
  198. /package/{shadcn → dist/shadcn}/components/ui/tabs.d.ts +0 -0
  199. /package/{shadcn → dist/shadcn}/components/ui/tabs.js +0 -0
  200. /package/{shadcn → dist/shadcn}/components/ui/tabs.js.map +0 -0
  201. /package/{shadcn → dist/shadcn}/components/ui/textarea.d.ts +0 -0
  202. /package/{shadcn → dist/shadcn}/components/ui/textarea.js +0 -0
  203. /package/{shadcn → dist/shadcn}/components/ui/textarea.js.map +0 -0
  204. /package/{shadcn → dist/shadcn}/components/ui/tooltip.d.ts +0 -0
  205. /package/{shadcn → dist/shadcn}/components/ui/tooltip.js +0 -0
  206. /package/{shadcn → dist/shadcn}/components/ui/tooltip.js.map +0 -0
  207. /package/{shadcn → dist/shadcn}/utils.d.ts +0 -0
  208. /package/{shadcn → dist/shadcn}/utils.js +0 -0
  209. /package/{shadcn → dist/shadcn}/utils.js.map +0 -0
  210. /package/{types → dist/types}/grapesjs-tailwind.d.js +0 -0
  211. /package/{types → dist/types}/grapesjs-tailwind.d.js.map +0 -0
  212. /package/{types → dist/types}/images.d.js +0 -0
  213. /package/{types → dist/types}/images.d.js.map +0 -0
@@ -0,0 +1,213 @@
1
+ import * as React from 'react';
2
+ import {
3
+ ChevronsLeft,
4
+ ChevronsRight,
5
+ ChevronLeft,
6
+ ChevronRight,
7
+ MoreHorizontalIcon,
8
+ } from 'lucide-react';
9
+
10
+ import { cn } from '../../utils';
11
+ import { Button, buttonVariants } from '../ui/button';
12
+
13
+ function Pagination({ className, ...props }: React.ComponentProps<'nav'>) {
14
+ return (
15
+ <nav
16
+ role="navigation"
17
+ aria-label="pagination"
18
+ data-slot="pagination"
19
+ className={cn('mx-auto flex w-full justify-center', className)}
20
+ {...props}
21
+ />
22
+ );
23
+ }
24
+
25
+ function PaginationContent({ className, ...props }: React.ComponentProps<'ul'>) {
26
+ return (
27
+ <ul
28
+ data-slot="pagination-content"
29
+ className={cn('flex flex-row items-center gap-1', className)}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function PaginationItem({ ...props }: React.ComponentProps<'li'>) {
36
+ return <li data-slot="pagination-item" {...props} />;
37
+ }
38
+
39
+ type PaginationLinkProps = {
40
+ isActive?: boolean;
41
+ isDisabled?: boolean;
42
+ } & Pick<React.ComponentProps<typeof Button>, 'size'> &
43
+ React.ComponentProps<'a'>;
44
+
45
+ function PaginationLink({
46
+ className,
47
+ isActive,
48
+ isDisabled = false,
49
+ size = 'sm',
50
+ ...props
51
+ }: PaginationLinkProps) {
52
+ return (
53
+ <a
54
+ aria-current={isActive ? 'page' : undefined}
55
+ data-slot="pagination-link"
56
+ data-active={isActive}
57
+ aria-disabled={isDisabled}
58
+ tabIndex={isDisabled ? -1 : 0}
59
+ className={cn(
60
+ buttonVariants({
61
+ variant: isActive ? 'outline' : 'ghost',
62
+ size,
63
+ }),
64
+ isDisabled && 'opacity-50 pointer-events-none',
65
+ 'cursor-pointer',
66
+ className,
67
+ )}
68
+ {...props}
69
+ />
70
+ );
71
+ }
72
+
73
+ function PaginationEllipsis({ className, ...props }: React.ComponentProps<'span'>) {
74
+ return (
75
+ <span
76
+ aria-hidden
77
+ data-slot="pagination-ellipsis"
78
+ className={cn('flex size-9 items-center justify-center', className)}
79
+ {...props}
80
+ >
81
+ <MoreHorizontalIcon className="size-4" />
82
+ <span className="sr-only">More pages</span>
83
+ </span>
84
+ );
85
+ }
86
+
87
+ function getVisiblePages(currentPage: number, allPages: number): number[] {
88
+ const pages: number[] = [];
89
+
90
+ if (allPages <= 3) {
91
+ for (let i = 1; i <= allPages; i++) {
92
+ pages.push(i);
93
+ }
94
+
95
+ return pages;
96
+ }
97
+
98
+ if (currentPage >= 3) {
99
+ pages.push(-1);
100
+ }
101
+
102
+ for (let i = currentPage - 1; i <= currentPage + 1; i++) {
103
+ if (i > 0 && i <= allPages) {
104
+ pages.push(i);
105
+ }
106
+ }
107
+
108
+ if (currentPage <= allPages - 2) {
109
+ pages.push(-2);
110
+ }
111
+
112
+ return pages;
113
+ }
114
+
115
+ function renderPaginationControls(
116
+ currentPage: number,
117
+ totalPages: number,
118
+ isLoading: boolean,
119
+ handlePageChange: (page: number) => void,
120
+ ) {
121
+ return getVisiblePages(currentPage, totalPages).map((page, idx) => {
122
+ if (page === -1) {
123
+ return (
124
+ <PaginationItem key={`left-ellipsis-${idx}`}>
125
+ <PaginationEllipsis />
126
+ </PaginationItem>
127
+ );
128
+ }
129
+
130
+ if (page === -2) {
131
+ return (
132
+ <PaginationItem key={`right-ellipsis-${idx}`}>
133
+ <PaginationEllipsis />
134
+ </PaginationItem>
135
+ );
136
+ }
137
+
138
+ return (
139
+ <PaginationItem key={page}>
140
+ <PaginationLink
141
+ isActive={page === currentPage}
142
+ onClick={isLoading ? undefined : () => handlePageChange(page)}
143
+ >
144
+ {page}
145
+ </PaginationLink>
146
+ </PaginationItem>
147
+ );
148
+ });
149
+ }
150
+
151
+ function renderPaginationArrows(
152
+ currentPage: number,
153
+ totalPages: number,
154
+ isLoading: boolean,
155
+ handlePageChange: (page: number) => void,
156
+ ) {
157
+ return (
158
+ <>
159
+ <PaginationItem>
160
+ <PaginationLink
161
+ onClick={currentPage === 1 || isLoading ? undefined : () => handlePageChange(1)}
162
+ isDisabled={currentPage === 1}
163
+ >
164
+ <ChevronsLeft className="size-4" />
165
+ </PaginationLink>
166
+ </PaginationItem>
167
+ <PaginationItem>
168
+ <PaginationLink
169
+ onClick={
170
+ currentPage === 1 || isLoading ? undefined : () => handlePageChange(currentPage - 1)
171
+ }
172
+ isDisabled={currentPage === 1}
173
+ >
174
+ <ChevronLeft className="size-4" />
175
+ </PaginationLink>
176
+ </PaginationItem>
177
+ {renderPaginationControls(currentPage, totalPages, isLoading, handlePageChange)}
178
+ <PaginationItem>
179
+ <PaginationLink
180
+ onClick={
181
+ currentPage === totalPages || isLoading
182
+ ? undefined
183
+ : () => handlePageChange(currentPage + 1)
184
+ }
185
+ isDisabled={currentPage === totalPages}
186
+ >
187
+ <ChevronRight className="size-4" />
188
+ </PaginationLink>
189
+ </PaginationItem>
190
+ <PaginationItem>
191
+ <PaginationLink
192
+ onClick={
193
+ currentPage === totalPages || isLoading ? undefined : () => handlePageChange(totalPages)
194
+ }
195
+ isDisabled={currentPage === totalPages}
196
+ >
197
+ <ChevronsRight className="size-4" />
198
+ </PaginationLink>
199
+ </PaginationItem>
200
+ </>
201
+ );
202
+ }
203
+
204
+ export {
205
+ Pagination,
206
+ PaginationContent,
207
+ PaginationLink,
208
+ PaginationItem,
209
+ PaginationEllipsis,
210
+ getVisiblePages,
211
+ renderPaginationControls,
212
+ renderPaginationArrows,
213
+ };
@@ -0,0 +1,59 @@
1
+ import * as React from 'react';
2
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
3
+
4
+ import { cn } from '../../utils';
5
+
6
+ type ScrollAreaProps = {
7
+ viewportClassName?: string;
8
+ hideScrollbars?: boolean;
9
+ } & React.ComponentProps<typeof ScrollAreaPrimitive.Root>;
10
+
11
+ function ScrollArea({ className, children, viewportClassName, hideScrollbars = false, ...props }: ScrollAreaProps) {
12
+ return (
13
+ <ScrollAreaPrimitive.Root
14
+ data-slot="scroll-area"
15
+ className={cn('relative', className)}
16
+ {...props}
17
+ >
18
+ <ScrollAreaPrimitive.Viewport
19
+ data-slot="scroll-area-viewport"
20
+ className={cn(
21
+ 'focus-visible:ring-ring/50 rounded-[inherit] outline-none focus-visible:ring-[3px]',
22
+ 'h-full w-full',
23
+ viewportClassName,
24
+ )}
25
+ >
26
+ {children}
27
+ </ScrollAreaPrimitive.Viewport>
28
+ {!hideScrollbars && <ScrollBar />}
29
+ <ScrollAreaPrimitive.Corner />
30
+ </ScrollAreaPrimitive.Root>
31
+ );
32
+ }
33
+
34
+ function ScrollBar({
35
+ className,
36
+ orientation = 'vertical',
37
+ ...props
38
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
39
+ return (
40
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
41
+ data-slot="scroll-area-scrollbar"
42
+ orientation={orientation}
43
+ className={cn(
44
+ 'flex touch-none p-px transition-colors select-none',
45
+ orientation === 'vertical' && 'h-full w-2.5 border-l border-l-transparent',
46
+ orientation === 'horizontal' && 'h-2.5 flex-col border-t border-t-transparent',
47
+ className,
48
+ )}
49
+ {...props}
50
+ >
51
+ <ScrollAreaPrimitive.ScrollAreaThumb
52
+ data-slot="scroll-area-thumb"
53
+ className="bg-border relative flex-1 rounded-xl"
54
+ />
55
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
56
+ );
57
+ }
58
+
59
+ export { ScrollArea, ScrollBar };
@@ -0,0 +1,150 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { Loader2Icon, Search as SearchIcon, X as ClearIcon, Info as InfoIcon } from 'lucide-react';
4
+ import { Input } from './input';
5
+ import { getAffectedComponentsWithLoader } from '../../../helpers';
6
+ import { Tooltip, TooltipTrigger, TooltipContent } from './tooltip';
7
+
8
+ const MAX_CHAR_LIMIT = 140;
9
+ const MaxCharLimitExceededMessage = 'Max 140 characters allowed.';
10
+
11
+ type SearchProps = {
12
+ isEditable?: boolean;
13
+ gjsModel: any;
14
+ performInteraction: (payload: Record<string, any>) => Promise<void>;
15
+ };
16
+
17
+ export function renderSearch({ gjsModel, performInteraction }: SearchProps) {
18
+ const wrapperRef = useRef<HTMLDivElement>(null);
19
+
20
+ const [componentData, setComponentData] = useState({ ...gjsModel.get('componentProps') });
21
+ const { placeholder, affectedComponents = [], className = '' } = componentData;
22
+ const initialSearchText = componentData.searchText || '';
23
+
24
+ const [attributes, setAttributes] = useState({ ...gjsModel.get('attributes') });
25
+ const [searchQuery, setSearchQuery] = useState(initialSearchText);
26
+ const [isApplying, setIsApplying] = useState(false);
27
+
28
+ const isBusy = attributes.interactionApiInProgress || isApplying;
29
+ const showClear = !!searchQuery && !isBusy;
30
+
31
+ useEffect(() => {
32
+ function updateComponentData() {
33
+ setComponentData({ ...gjsModel.get('componentProps') });
34
+ }
35
+
36
+ function updateAttributes() {
37
+ setAttributes({ ...gjsModel.get('attributes') });
38
+ }
39
+
40
+ gjsModel.on('change:componentProps', updateComponentData);
41
+ gjsModel.on('change:attributes', updateAttributes);
42
+
43
+ return () => {
44
+ gjsModel.off('change:componentProps', updateComponentData);
45
+ gjsModel.off('change:attributes', updateAttributes);
46
+ };
47
+ }, [gjsModel]);
48
+
49
+ async function applySearch(query: string) {
50
+ if (query.length > MAX_CHAR_LIMIT) {
51
+ return;
52
+ }
53
+
54
+ setIsApplying(true);
55
+
56
+ try {
57
+ gjsModel.set('componentProps', {
58
+ ...gjsModel.get('componentProps'),
59
+ searchText: query,
60
+ });
61
+
62
+ const id = gjsModel.get('id');
63
+
64
+ await performInteraction({
65
+ interactionType: 'search',
66
+ id,
67
+ affectedComponents: getAffectedComponentsWithLoader([id, ...affectedComponents], true),
68
+ });
69
+ } finally {
70
+ setIsApplying(false);
71
+ }
72
+ }
73
+
74
+ function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
75
+ if (e.key === 'Enter') {
76
+ applySearch(searchQuery.trim());
77
+ }
78
+ }
79
+
80
+ function handleSearchIconClick() {
81
+ applySearch(searchQuery.trim());
82
+ }
83
+
84
+ function handleClear() {
85
+ setSearchQuery('');
86
+ applySearch('');
87
+ }
88
+
89
+ return (
90
+ <div ref={wrapperRef} className={`flex items-center gap-2 p-2 ${className}`}>
91
+ <div
92
+ className={`relative transition-all duration-200 ease-in-out ${
93
+ searchQuery ? 'w-[320px]' : 'w-[280px]'
94
+ }`}
95
+ style={{ backgroundColor: '#fff' }}
96
+ >
97
+ <div>
98
+ <Input
99
+ type="text"
100
+ data-slot="search-input"
101
+ placeholder={'Search...'}
102
+ value={searchQuery}
103
+ onChange={(e) => setSearchQuery(e.target.value)}
104
+ onKeyDown={handleKeyDown}
105
+ disabled={isBusy}
106
+ className={`py-2 text-sm rounded-md border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all duration-200 pl-4 pr-16 w-full`}
107
+ />
108
+
109
+ {showClear && (
110
+ <button
111
+ type="button"
112
+ onClick={handleClear}
113
+ className="absolute right-10 top-7 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition"
114
+ aria-label="Clear search"
115
+ >
116
+ <ClearIcon size={16} />
117
+ </button>
118
+ )}
119
+
120
+ <button
121
+ type="button"
122
+ onClick={handleSearchIconClick}
123
+ disabled={isBusy}
124
+ className="absolute right-2 top-7 -translate-y-1/2 text-gray-500 hover:text-blue-600 transition-colors"
125
+ aria-label="Search"
126
+ >
127
+ {isBusy ? <Loader2Icon size={18} className="animate-spin" /> : <SearchIcon size={18} />}
128
+ </button>
129
+ </div>
130
+
131
+ {searchQuery.length > MAX_CHAR_LIMIT && (
132
+ <p className="absolute left-1 text-xs text-red-600 pl-1 pt-1">
133
+ {MaxCharLimitExceededMessage}
134
+ </p>
135
+ )}
136
+ </div>
137
+
138
+ {placeholder && (
139
+ <Tooltip>
140
+ <TooltipTrigger asChild>
141
+ <span className="cursor-pointer text-gray-400 hover:text-gray-600">
142
+ <InfoIcon size={16} />
143
+ </span>
144
+ </TooltipTrigger>
145
+ <TooltipContent side="bottom">{placeholder}</TooltipContent>
146
+ </Tooltip>
147
+ )}
148
+ </div>
149
+ );
150
+ }
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
3
+
4
+ import { cn } from '../../utils';
5
+
6
+ function Separator({
7
+ className,
8
+ orientation = 'horizontal',
9
+ decorative = true,
10
+ ...props
11
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
12
+ return (
13
+ <SeparatorPrimitive.Root
14
+ data-slot="separator-root"
15
+ decorative={decorative}
16
+ orientation={orientation}
17
+ className={cn(
18
+ 'w-4/5 border-gray-300 my-6 shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px',
19
+ className,
20
+ )}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+
26
+ export { Separator };
@@ -0,0 +1,69 @@
1
+ import { cn } from '../../utils';
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("bg-accent animate-pulse rounded-md", className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ function TableLoader({ count = 5 }) {
14
+ return (
15
+ <div className='flex flex-row gap-6'>
16
+ {
17
+ Array.from({ length: 3 }).map((_, colIndex) => {
18
+ return (
19
+ <div className="flex flex-col gap-3 w-1/3" key={`col-${colIndex}`}>
20
+ <Skeleton className="w-full h-10" />
21
+ {Array.from({ length: count }).map((_, index) => (
22
+ <Skeleton className="w-full h-6" key={index} />
23
+ ))}
24
+ </div>
25
+ )
26
+ })
27
+ }
28
+ </div>
29
+ );
30
+ }
31
+
32
+ function ChartLoader() {
33
+ return (
34
+ <div className="flex flex-col gap-4">
35
+ <div className='flex flex-row gap-4'>
36
+ <Skeleton className="h-40 w-1/6 self-end" />
37
+ <Skeleton className="h-50 w-1/6 self-end" />
38
+ <Skeleton className="h-30 w-1/6 self-end" />
39
+ <Skeleton className="h-40 w-1/6 self-end" />
40
+ <Skeleton className="h-50 w-1/6 self-end" />
41
+ <Skeleton className="h-20 w-1/6 self-end" />
42
+ </div>
43
+ <Skeleton className="w-full h-5" />
44
+ </div>
45
+ );
46
+ }
47
+
48
+ function CardLoader() {
49
+ return (
50
+ <div className='flex flex-col gap-1'>
51
+ <Skeleton className="h-5 w-full" />
52
+ <Skeleton className="h-3 w-full" />
53
+ <Skeleton className="h-10 w-full" />
54
+ <Skeleton className="h-5 w-full" />
55
+ </div>
56
+ );
57
+ }
58
+
59
+ function MarkdownLoader() {
60
+ return (
61
+ <div className='flex flex-col gap-2'>
62
+ <Skeleton className="h-5 w-full bg-black/10" />
63
+ <Skeleton className="h-5 w-full bg-black/10" />
64
+ <Skeleton className="h-5 w-full bg-black/10" />
65
+ </div>
66
+ );
67
+ }
68
+
69
+ export { Skeleton, TableLoader, ChartLoader, CardLoader, MarkdownLoader, }