@peak-ai/canvas 1.4.22 → 1.4.23-rc.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 (213) hide show
  1. package/helpers/filter-placeholder.js +4 -0
  2. package/helpers/filter-placeholder.js.map +1 -0
  3. package/package.json +6 -44
  4. package/plugins/helpers/render-components.js +15 -0
  5. package/plugins/helpers/render-components.js.map +1 -0
  6. package/.babelrc +0 -14
  7. package/.eslintcache +0 -1
  8. package/.eslintignore +0 -5
  9. package/.eslintrc.js +0 -29
  10. package/dist/helpers/filter-placeholder.js +0 -3
  11. package/dist/helpers/filter-placeholder.js.map +0 -1
  12. package/dist/package.json +0 -62
  13. package/dist/plugins/helpers/render-components.js +0 -10
  14. package/dist/plugins/helpers/render-components.js.map +0 -1
  15. package/scripts/build.ts +0 -120
  16. package/src/GrapesjsCanvas.tsx +0 -494
  17. package/src/constants/index.ts +0 -25
  18. package/src/declaration.d.ts +0 -1
  19. package/src/helpers/compiled-table.css +0 -2429
  20. package/src/helpers/css.ts +0 -2667
  21. package/src/helpers/date-picker.ts +0 -807
  22. package/src/helpers/filter-placeholder.ts +0 -18
  23. package/src/helpers/index.ts +0 -13
  24. package/src/helpers/merge-json.ts +0 -106
  25. package/src/index.styles.ts +0 -58
  26. package/src/index.ts +0 -9
  27. package/src/plugins/grapejs-plugin.tsx +0 -196
  28. package/src/plugins/helpers/custom-modal.tsx +0 -123
  29. package/src/plugins/helpers/data-table.tsx +0 -300
  30. package/src/plugins/helpers/extra.tsx +0 -164
  31. package/src/plugins/helpers/query-cache-context.tsx +0 -154
  32. package/src/plugins/helpers/query-cache-singleton.ts +0 -176
  33. package/src/plugins/helpers/query-cache-utils.ts +0 -226
  34. package/src/plugins/helpers/query-details-modal.tsx +0 -400
  35. package/src/plugins/helpers/query-heading-formatter.ts +0 -24
  36. package/src/plugins/helpers/query-loading-modal.tsx +0 -94
  37. package/src/plugins/helpers/render-components.tsx +0 -1450
  38. package/src/plugins/helpers/styled-info-button.tsx +0 -504
  39. package/src/public/canvas.css +0 -42
  40. package/src/public/components-css/table/table-output.css +0 -2436
  41. package/src/public/components-css/table/table.css +0 -30
  42. package/src/public/output.css +0 -2465
  43. package/src/public/table.css +0 -135
  44. package/src/shadcn/components/icons/AiAvatarIcon.tsx +0 -47
  45. package/src/shadcn/components/icons/Co_driver Expanding button copy.svg +0 -21
  46. package/src/shadcn/components/icons/ai-avatar.svg +0 -7
  47. package/src/shadcn/components/icons/thinking.gif +0 -0
  48. package/src/shadcn/components/ui/button.tsx +0 -132
  49. package/src/shadcn/components/ui/card.tsx +0 -92
  50. package/src/shadcn/components/ui/chart.tsx +0 -324
  51. package/src/shadcn/components/ui/checkbox.tsx +0 -27
  52. package/src/shadcn/components/ui/component-wrapper.tsx +0 -61
  53. package/src/shadcn/components/ui/date-filter.tsx +0 -816
  54. package/src/shadcn/components/ui/error-container.tsx +0 -125
  55. package/src/shadcn/components/ui/error-wrapper.tsx +0 -99
  56. package/src/shadcn/components/ui/filter.tsx +0 -368
  57. package/src/shadcn/components/ui/hover-card.tsx +0 -36
  58. package/src/shadcn/components/ui/input.tsx +0 -20
  59. package/src/shadcn/components/ui/label.tsx +0 -24
  60. package/src/shadcn/components/ui/pagination.tsx +0 -213
  61. package/src/shadcn/components/ui/scroll-area.tsx +0 -59
  62. package/src/shadcn/components/ui/search.tsx +0 -150
  63. package/src/shadcn/components/ui/separator.tsx +0 -26
  64. package/src/shadcn/components/ui/skeleton.tsx +0 -69
  65. package/src/shadcn/components/ui/table.tsx +0 -196
  66. package/src/shadcn/components/ui/tabs.tsx +0 -55
  67. package/src/shadcn/components/ui/textarea.tsx +0 -18
  68. package/src/shadcn/components/ui/tooltip.tsx +0 -87
  69. package/src/shadcn/utils.ts +0 -6
  70. package/src/types/grapesjs-tailwind.d.ts +0 -61
  71. package/src/types/images.d.ts +0 -1
  72. package/tailwind.config.js +0 -5
  73. package/tooling/tailwind-compiler/index.js +0 -99
  74. package/tooling/tailwind-compiler/package.json +0 -11
  75. package/tooling/tailwind-compiler/yarn.lock +0 -123
  76. package/tsconfig.build.json +0 -15
  77. package/tsconfig.json +0 -8
  78. /package/{dist/GrapesjsCanvas.d.ts → GrapesjsCanvas.d.ts} +0 -0
  79. /package/{dist/GrapesjsCanvas.js → GrapesjsCanvas.js} +0 -0
  80. /package/{dist/GrapesjsCanvas.js.map → GrapesjsCanvas.js.map} +0 -0
  81. /package/{dist/constants → constants}/index.d.ts +0 -0
  82. /package/{dist/constants → constants}/index.js +0 -0
  83. /package/{dist/constants → constants}/index.js.map +0 -0
  84. /package/{dist/declaration.d.js → declaration.d.js} +0 -0
  85. /package/{dist/declaration.d.js.map → declaration.d.js.map} +0 -0
  86. /package/{dist/helpers → helpers}/compiled-table.css +0 -0
  87. /package/{dist/helpers → helpers}/css.d.ts +0 -0
  88. /package/{dist/helpers → helpers}/css.js +0 -0
  89. /package/{dist/helpers → helpers}/css.js.map +0 -0
  90. /package/{dist/helpers → helpers}/date-picker.d.ts +0 -0
  91. /package/{dist/helpers → helpers}/date-picker.js +0 -0
  92. /package/{dist/helpers → helpers}/date-picker.js.map +0 -0
  93. /package/{dist/helpers → helpers}/filter-placeholder.d.ts +0 -0
  94. /package/{dist/helpers → helpers}/index.d.ts +0 -0
  95. /package/{dist/helpers → helpers}/index.js +0 -0
  96. /package/{dist/helpers → helpers}/index.js.map +0 -0
  97. /package/{dist/helpers → helpers}/merge-json.d.ts +0 -0
  98. /package/{dist/helpers → helpers}/merge-json.js +0 -0
  99. /package/{dist/helpers → helpers}/merge-json.js.map +0 -0
  100. /package/{dist/index.d.ts → index.d.ts} +0 -0
  101. /package/{dist/index.js → index.js} +0 -0
  102. /package/{dist/index.js.map → index.js.map} +0 -0
  103. /package/{dist/index.styles.d.ts → index.styles.d.ts} +0 -0
  104. /package/{dist/index.styles.js → index.styles.js} +0 -0
  105. /package/{dist/index.styles.js.map → index.styles.js.map} +0 -0
  106. /package/{dist/plugins → plugins}/grapejs-plugin.d.ts +0 -0
  107. /package/{dist/plugins → plugins}/grapejs-plugin.js +0 -0
  108. /package/{dist/plugins → plugins}/grapejs-plugin.js.map +0 -0
  109. /package/{dist/plugins → plugins}/helpers/custom-modal.d.ts +0 -0
  110. /package/{dist/plugins → plugins}/helpers/custom-modal.js +0 -0
  111. /package/{dist/plugins → plugins}/helpers/custom-modal.js.map +0 -0
  112. /package/{dist/plugins → plugins}/helpers/data-table.d.ts +0 -0
  113. /package/{dist/plugins → plugins}/helpers/data-table.js +0 -0
  114. /package/{dist/plugins → plugins}/helpers/data-table.js.map +0 -0
  115. /package/{dist/plugins → plugins}/helpers/extra.d.ts +0 -0
  116. /package/{dist/plugins → plugins}/helpers/extra.js +0 -0
  117. /package/{dist/plugins → plugins}/helpers/extra.js.map +0 -0
  118. /package/{dist/plugins → plugins}/helpers/query-cache-context.d.ts +0 -0
  119. /package/{dist/plugins → plugins}/helpers/query-cache-context.js +0 -0
  120. /package/{dist/plugins → plugins}/helpers/query-cache-context.js.map +0 -0
  121. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.d.ts +0 -0
  122. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.js +0 -0
  123. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.js.map +0 -0
  124. /package/{dist/plugins → plugins}/helpers/query-cache-utils.d.ts +0 -0
  125. /package/{dist/plugins → plugins}/helpers/query-cache-utils.js +0 -0
  126. /package/{dist/plugins → plugins}/helpers/query-cache-utils.js.map +0 -0
  127. /package/{dist/plugins → plugins}/helpers/query-details-modal.d.ts +0 -0
  128. /package/{dist/plugins → plugins}/helpers/query-details-modal.js +0 -0
  129. /package/{dist/plugins → plugins}/helpers/query-details-modal.js.map +0 -0
  130. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.d.ts +0 -0
  131. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.js +0 -0
  132. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.js.map +0 -0
  133. /package/{dist/plugins → plugins}/helpers/query-loading-modal.d.ts +0 -0
  134. /package/{dist/plugins → plugins}/helpers/query-loading-modal.js +0 -0
  135. /package/{dist/plugins → plugins}/helpers/query-loading-modal.js.map +0 -0
  136. /package/{dist/plugins → plugins}/helpers/render-components.d.ts +0 -0
  137. /package/{dist/plugins → plugins}/helpers/styled-info-button.d.ts +0 -0
  138. /package/{dist/plugins → plugins}/helpers/styled-info-button.js +0 -0
  139. /package/{dist/plugins → plugins}/helpers/styled-info-button.js.map +0 -0
  140. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.d.ts +0 -0
  141. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.js +0 -0
  142. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.js.map +0 -0
  143. /package/{dist/shadcn → shadcn}/components/icons/thinking.gif +0 -0
  144. /package/{dist/shadcn → shadcn}/components/ui/button.d.ts +0 -0
  145. /package/{dist/shadcn → shadcn}/components/ui/button.js +0 -0
  146. /package/{dist/shadcn → shadcn}/components/ui/button.js.map +0 -0
  147. /package/{dist/shadcn → shadcn}/components/ui/card.d.ts +0 -0
  148. /package/{dist/shadcn → shadcn}/components/ui/card.js +0 -0
  149. /package/{dist/shadcn → shadcn}/components/ui/card.js.map +0 -0
  150. /package/{dist/shadcn → shadcn}/components/ui/chart.d.ts +0 -0
  151. /package/{dist/shadcn → shadcn}/components/ui/chart.js +0 -0
  152. /package/{dist/shadcn → shadcn}/components/ui/chart.js.map +0 -0
  153. /package/{dist/shadcn → shadcn}/components/ui/checkbox.d.ts +0 -0
  154. /package/{dist/shadcn → shadcn}/components/ui/checkbox.js +0 -0
  155. /package/{dist/shadcn → shadcn}/components/ui/checkbox.js.map +0 -0
  156. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.d.ts +0 -0
  157. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.js +0 -0
  158. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.js.map +0 -0
  159. /package/{dist/shadcn → shadcn}/components/ui/date-filter.d.ts +0 -0
  160. /package/{dist/shadcn → shadcn}/components/ui/date-filter.js +0 -0
  161. /package/{dist/shadcn → shadcn}/components/ui/date-filter.js.map +0 -0
  162. /package/{dist/shadcn → shadcn}/components/ui/error-container.d.ts +0 -0
  163. /package/{dist/shadcn → shadcn}/components/ui/error-container.js +0 -0
  164. /package/{dist/shadcn → shadcn}/components/ui/error-container.js.map +0 -0
  165. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.d.ts +0 -0
  166. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.js +0 -0
  167. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.js.map +0 -0
  168. /package/{dist/shadcn → shadcn}/components/ui/filter.d.ts +0 -0
  169. /package/{dist/shadcn → shadcn}/components/ui/filter.js +0 -0
  170. /package/{dist/shadcn → shadcn}/components/ui/filter.js.map +0 -0
  171. /package/{dist/shadcn → shadcn}/components/ui/hover-card.d.ts +0 -0
  172. /package/{dist/shadcn → shadcn}/components/ui/hover-card.js +0 -0
  173. /package/{dist/shadcn → shadcn}/components/ui/hover-card.js.map +0 -0
  174. /package/{dist/shadcn → shadcn}/components/ui/input.d.ts +0 -0
  175. /package/{dist/shadcn → shadcn}/components/ui/input.js +0 -0
  176. /package/{dist/shadcn → shadcn}/components/ui/input.js.map +0 -0
  177. /package/{dist/shadcn → shadcn}/components/ui/label.d.ts +0 -0
  178. /package/{dist/shadcn → shadcn}/components/ui/label.js +0 -0
  179. /package/{dist/shadcn → shadcn}/components/ui/label.js.map +0 -0
  180. /package/{dist/shadcn → shadcn}/components/ui/pagination.d.ts +0 -0
  181. /package/{dist/shadcn → shadcn}/components/ui/pagination.js +0 -0
  182. /package/{dist/shadcn → shadcn}/components/ui/pagination.js.map +0 -0
  183. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.d.ts +0 -0
  184. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.js +0 -0
  185. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.js.map +0 -0
  186. /package/{dist/shadcn → shadcn}/components/ui/search.d.ts +0 -0
  187. /package/{dist/shadcn → shadcn}/components/ui/search.js +0 -0
  188. /package/{dist/shadcn → shadcn}/components/ui/search.js.map +0 -0
  189. /package/{dist/shadcn → shadcn}/components/ui/separator.d.ts +0 -0
  190. /package/{dist/shadcn → shadcn}/components/ui/separator.js +0 -0
  191. /package/{dist/shadcn → shadcn}/components/ui/separator.js.map +0 -0
  192. /package/{dist/shadcn → shadcn}/components/ui/skeleton.d.ts +0 -0
  193. /package/{dist/shadcn → shadcn}/components/ui/skeleton.js +0 -0
  194. /package/{dist/shadcn → shadcn}/components/ui/skeleton.js.map +0 -0
  195. /package/{dist/shadcn → shadcn}/components/ui/table.d.ts +0 -0
  196. /package/{dist/shadcn → shadcn}/components/ui/table.js +0 -0
  197. /package/{dist/shadcn → shadcn}/components/ui/table.js.map +0 -0
  198. /package/{dist/shadcn → shadcn}/components/ui/tabs.d.ts +0 -0
  199. /package/{dist/shadcn → shadcn}/components/ui/tabs.js +0 -0
  200. /package/{dist/shadcn → shadcn}/components/ui/tabs.js.map +0 -0
  201. /package/{dist/shadcn → shadcn}/components/ui/textarea.d.ts +0 -0
  202. /package/{dist/shadcn → shadcn}/components/ui/textarea.js +0 -0
  203. /package/{dist/shadcn → shadcn}/components/ui/textarea.js.map +0 -0
  204. /package/{dist/shadcn → shadcn}/components/ui/tooltip.d.ts +0 -0
  205. /package/{dist/shadcn → shadcn}/components/ui/tooltip.js +0 -0
  206. /package/{dist/shadcn → shadcn}/components/ui/tooltip.js.map +0 -0
  207. /package/{dist/shadcn → shadcn}/utils.d.ts +0 -0
  208. /package/{dist/shadcn → shadcn}/utils.js +0 -0
  209. /package/{dist/shadcn → shadcn}/utils.js.map +0 -0
  210. /package/{dist/types → types}/grapesjs-tailwind.d.js +0 -0
  211. /package/{dist/types → types}/grapesjs-tailwind.d.js.map +0 -0
  212. /package/{dist/types → types}/images.d.js +0 -0
  213. /package/{dist/types → types}/images.d.js.map +0 -0
@@ -1,400 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import { CustomModal } from './custom-modal';
3
- import { Copy, Check, ChevronDown, ChevronUp, X } from 'lucide-react';
4
- import { formatQueryHeading } from './query-heading-formatter';
5
-
6
- type CopyButtonProps = {
7
- onClick: () => void;
8
- isCopied: boolean;
9
- variant?: 'default' | 'light';
10
- };
11
-
12
- function CopyButton({ onClick, isCopied, variant = 'default' }: CopyButtonProps) {
13
- const baseClasses = "flex items-center gap-1 px-2 py-1 text-xs border rounded transition-colors";
14
- const variantClasses = variant === 'light'
15
- ? "bg-gray-50 border-gray-300 hover:bg-gray-100"
16
- : "bg-gray-100 border-gray-300 hover:bg-gray-200";
17
-
18
- return (
19
- <button
20
- onClick={onClick}
21
- className={`${baseClasses} ${variantClasses}`}
22
- type="button"
23
- >
24
- {isCopied ? (
25
- <>
26
- <Check className="w-3 h-3 text-green-600" />
27
- <span className="text-green-600">Copied!</span>
28
- </>
29
- ) : (
30
- <>
31
- <Copy className="w-3 h-3 text-gray-600" />
32
- <span className="text-gray-600">Copy</span>
33
- </>
34
- )}
35
- </button>
36
- );
37
- }
38
-
39
- type ContentTextProps = {
40
- children: React.ReactNode;
41
- hasOverflowHandling?: boolean;
42
- };
43
-
44
- function ContentText({ children, hasOverflowHandling = true }: ContentTextProps) {
45
- const overflowClasses = hasOverflowHandling ? "overflow-hidden break-words" : "";
46
-
47
- return (
48
- <pre className={`whitespace-pre-wrap leading-relaxed text-xs text-gray-700 m-0 p-0 ${overflowClasses}`}>
49
- {children}
50
- </pre>
51
- );
52
- }
53
-
54
- type ContentBlockProps = {
55
- title: string;
56
- children: React.ReactNode;
57
- copyContent?: string;
58
- copyId: string;
59
- copied: Record<string, boolean>;
60
- onCopy: (content: string, id: string) => void;
61
- variant?: 'default' | 'bordered';
62
- copyButtonVariant?: 'default' | 'light';
63
- };
64
-
65
- function ContentBlock({
66
- title,
67
- children,
68
- copyContent,
69
- copyId,
70
- copied,
71
- onCopy,
72
- variant = 'bordered',
73
- copyButtonVariant = 'default'
74
- }: ContentBlockProps) {
75
- const containerClasses = variant === 'bordered'
76
- ? "rounded-lg p-3"
77
- : "bg-white border border-gray-200 rounded-lg p-4";
78
-
79
- const containerStyle = variant === 'bordered'
80
- ? { border: '1px solid #E9EAF5' }
81
- : {};
82
-
83
- const titleClasses = variant === 'bordered'
84
- ? "text-sm font-medium text-gray-600"
85
- : "font-semibold text-sm text-gray-500 m-0";
86
-
87
- return (
88
- <div className={containerClasses} style={containerStyle}>
89
- <div className="flex justify-between items-start mb-2">
90
- <span className={titleClasses}>{title}</span>
91
- {copyContent && (
92
- <CopyButton
93
- onClick={() => onCopy(copyContent, copyId)}
94
- isCopied={copied[copyId] || false}
95
- variant={copyButtonVariant}
96
- />
97
- )}
98
- </div>
99
- {children}
100
- </div>
101
- );
102
- }
103
-
104
- type QueryDetailsModalProps = {
105
- isOpen: boolean;
106
- onClose: () => void;
107
- isLoading: boolean;
108
- error: string;
109
- sqlQuery: string | string[];
110
- queryHeadings?: string[];
111
- tableButtonExplanations?: Array<{
112
- action: string,
113
- explanation: string,
114
- operationSummary?: string,
115
- operationDescription?: string,
116
- buttonClassName?: string,
117
- buttonStyle?: Record<string, unknown>,
118
- formFields?: Record<string, unknown>;
119
- jsonBody?: unknown;
120
- requestUrl?: string;
121
- }>;
122
- onRetry: () => void;
123
- };
124
-
125
- export function QueryDetailsModal({
126
- isOpen,
127
- onClose,
128
- isLoading,
129
- error,
130
- sqlQuery,
131
- queryHeadings = [],
132
- tableButtonExplanations = [],
133
- onRetry
134
- }: QueryDetailsModalProps) {
135
- const [copied, setCopied] = useState<{ [key: string]: boolean }>({});
136
- const [expandedButtons, setExpandedButtons] = useState<{ [key: string]: boolean }>({});
137
-
138
- // Reset expanded state when modal closes
139
- useEffect(() => {
140
- if (!isOpen) {
141
- setExpandedButtons({});
142
- }
143
- }, [isOpen]);
144
-
145
- async function copyToClipboard(queryToCopy?: string, copyId?: string) {
146
- let textToCopy = queryToCopy;
147
-
148
- if (!textToCopy) {
149
- if (Array.isArray(sqlQuery)) {
150
- textToCopy = sqlQuery.filter(q => q && typeof q === 'string').join('\n\n-- Next Query --\n\n');
151
- } else if (typeof sqlQuery === 'string') {
152
- textToCopy = sqlQuery;
153
- } else {
154
- textToCopy = '';
155
- }
156
- }
157
-
158
- if (!textToCopy) {
159
- return;
160
- }
161
-
162
- const id = copyId || 'main';
163
-
164
- try {
165
- await navigator.clipboard.writeText(textToCopy);
166
- setCopied(prev => ({ ...prev, [id]: true }));
167
- setTimeout(() => setCopied(prev => ({ ...prev, [id]: false })), 2000);
168
- } catch (err) {
169
- // Silently fail if clipboard API is not available
170
- }
171
- }
172
-
173
- function toggleButtonExpansion(buttonIndex: number) {
174
- setExpandedButtons(prev => ({
175
- ...prev,
176
- [buttonIndex]: !prev[buttonIndex]
177
- }));
178
- }
179
-
180
- function renderTableButtonExplanations() {
181
- if (!tableButtonExplanations || tableButtonExplanations.length === 0) {
182
- return null;
183
- }
184
-
185
- function hasValidJsonBody(jsonBody: unknown): boolean {
186
- return jsonBody !== null && jsonBody !== undefined && jsonBody !== '';
187
- }
188
-
189
- function hasValidFormFields(formFields: Record<string, unknown> | undefined): boolean {
190
- return formFields !== null && formFields !== undefined && Object.keys(formFields || {}).length > 0;
191
- }
192
-
193
- return (
194
- <div className="mb-6">
195
- {tableButtonExplanations.map((button, index) => (
196
- <div key={index} className="mb-3 border border-gray-200 rounded-lg">
197
- <div className="w-full px-4 py-3 flex items-center justify-between rounded-lg">
198
- <div className="flex items-center">
199
- <button
200
- onClick={() => toggleButtonExpansion(index)}
201
- className={button.buttonClassName || "flex items-center justify-center px-3 rounded text-xs font-medium"}
202
- style={{
203
- height: '35px',
204
- width: 'fit-content',
205
- minWidth: 'fit-content',
206
- backgroundColor: (button.buttonStyle?.backgroundColor as string),
207
- color: (button.buttonStyle?.color as string),
208
- border: (button.buttonStyle?.border as string),
209
- ...(button.buttonStyle as React.CSSProperties || {})
210
- , ...button.buttonStyle as React.CSSProperties || {},
211
- display: 'flex',
212
- alignItems: 'center',
213
- justifyContent: 'center'
214
- }}
215
- >
216
- {button.action}
217
- </button>
218
- <div className="ml-3 flex flex-col">
219
- {button.operationSummary && (
220
- <span className="text-xs text-gray-700 font-medium">
221
- {button.operationSummary}
222
- </span>
223
- )}
224
- </div>
225
- </div>
226
- {expandedButtons[index] ? (
227
- <ChevronUp
228
- className="w-4 h-4 text-gray-500 transition-transform cursor-pointer"
229
- onClick={() => toggleButtonExpansion(index)}
230
- />
231
- ) : (
232
- <ChevronDown
233
- className="w-4 h-4 text-gray-500 transition-transform cursor-pointer"
234
- onClick={() => toggleButtonExpansion(index)}
235
- />
236
- )}
237
- </div>
238
-
239
- {expandedButtons[index] && (
240
- <div className="px-4 pb-3 border-t border-gray-200">
241
- <div className="mt-2 space-y-3">
242
- {/* Description Block */}
243
- {button.operationDescription && (
244
- <ContentBlock
245
- title="Description"
246
- copyId={`description-${index}`}
247
- copied={copied}
248
- onCopy={copyToClipboard}
249
- variant="bordered"
250
- >
251
- <ContentText>
252
- {button.operationDescription}
253
- </ContentText>
254
- </ContentBlock>
255
- )}
256
-
257
- {(button.requestUrl || button.explanation) && (
258
- <ContentBlock
259
- title="URL"
260
- copyContent={button.requestUrl || button.explanation}
261
- copyId={`url-${index}`}
262
- copied={copied}
263
- onCopy={copyToClipboard}
264
- variant="bordered"
265
- >
266
- <ContentText>
267
- {button.requestUrl || button.explanation}
268
- </ContentText>
269
- </ContentBlock>
270
- )}
271
-
272
- {(hasValidJsonBody(button.jsonBody) || hasValidFormFields(button.formFields)) && (
273
- <ContentBlock
274
- title="Payload"
275
- copyContent={JSON.stringify(
276
- hasValidJsonBody(button.jsonBody) ? button.jsonBody : button.formFields,
277
- null,
278
- 2
279
- )}
280
- copyId={`payload-${index}`}
281
- copied={copied}
282
- onCopy={copyToClipboard}
283
- variant="bordered"
284
- >
285
- <ContentText>
286
- {hasValidJsonBody(button.jsonBody)
287
- ? JSON.stringify(button.jsonBody, null, 2)
288
- : JSON.stringify(button.formFields, null, 2)}
289
- </ContentText>
290
- </ContentBlock>
291
- )}
292
- </div>
293
- </div>
294
- )}
295
- </div>
296
- ))}
297
- </div>
298
- );
299
- }
300
-
301
- function renderModalContent() {
302
- if (isLoading) {
303
- return (
304
- <div className="flex flex-col items-center justify-center py-12">
305
- <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mb-4"></div>
306
- <span className="text-xs text-gray-600">Fetching query details from semantic layer...</span>
307
- <span className="text-xs text-gray-400 mt-2">This may take a few moments</span>
308
- </div>
309
- );
310
- }
311
-
312
- if (error) {
313
- return (
314
- <div className="text-red-600 p-4 bg-red-50 rounded-lg border border-red-200 m-6">
315
- <p className="font-medium mb-2 text-xs">Unable to fetch query details</p>
316
- <p className="text-xs mb-3">{error}</p>
317
- <button
318
- onClick={onRetry}
319
- className="px-4 py-2 bg-red-100 hover:bg-red-200 rounded text-xs font-medium transition-colors"
320
- type="button"
321
- >
322
- Retry
323
- </button>
324
- </div>
325
- );
326
- }
327
-
328
- if (!sqlQuery || (Array.isArray(sqlQuery) && sqlQuery.length === 0)) {
329
- return (
330
- <div className="text-gray-600 p-6">
331
- <p className="text-xs">No query details available</p>
332
- </div>
333
- );
334
- }
335
-
336
- // Handle multiple queries
337
- if (Array.isArray(sqlQuery)) {
338
- return (
339
- <div className="p-6 space-y-4">
340
- {sqlQuery
341
- .filter(query => query && typeof query === 'string' && query.trim())
342
- .map((query, index) => {
343
-
344
- const rawHeading = queryHeadings[index] || `Query ${index + 1}`;
345
- const heading = formatQueryHeading(rawHeading);
346
-
347
- return (
348
- <ContentBlock
349
- key={index}
350
- title={heading}
351
- copyContent={query}
352
- copyId={`query-${index}`}
353
- copied={copied}
354
- onCopy={copyToClipboard}
355
- variant="default"
356
- copyButtonVariant="light"
357
- >
358
- <ContentText hasOverflowHandling={false}>
359
- {query}
360
- </ContentText>
361
- </ContentBlock>
362
- );
363
- })}
364
- {renderTableButtonExplanations()}
365
- </div>
366
- );
367
- }
368
-
369
- return (
370
- <div className="p-6 space-y-4">
371
- <ContentBlock
372
- title={formatQueryHeading(queryHeadings[0] || "Query details")}
373
- copyContent={typeof sqlQuery === 'string' ? sqlQuery : ''}
374
- copyId="single"
375
- copied={copied}
376
- onCopy={copyToClipboard}
377
- variant="default"
378
- copyButtonVariant="light"
379
- >
380
- <ContentText hasOverflowHandling={false}>
381
- {sqlQuery}
382
- </ContentText>
383
- </ContentBlock>
384
- {renderTableButtonExplanations()}
385
- </div>
386
- );
387
- }
388
-
389
- return (
390
- <CustomModal
391
- isOpen={isOpen}
392
- onClose={onClose}
393
- title="How was this metric calculated?"
394
- >
395
- {renderModalContent()}
396
- </CustomModal>
397
- );
398
- }
399
-
400
- export default QueryDetailsModal;
@@ -1,24 +0,0 @@
1
- /**
2
- * Utility function to format query headings for display
3
- * Converts technical query keys into presentable headings
4
- */
5
- export function formatQueryHeading(heading: string): string {
6
- if (!heading) {
7
- return 'Query details';
8
- }
9
-
10
- let formatted = heading.replace(/_[a-z-]+-[a-z0-9]+$/i, '');
11
-
12
- formatted = formatted.replace(/_/g, ' ');
13
-
14
- formatted = formatted.replace(/([a-z])([A-Z])/g, '$1 $2');
15
-
16
- const componentRegex = /\b(table|chart|card|button|text|image|list|modal|dropdown|tabs|header|footer|nav|menu|pagination|search|filter|sort|pagination)\b/gi;
17
- formatted = formatted.replace(componentRegex, '').trim();
18
-
19
- formatted = formatted.replace(/\b\w/g, l => l.toUpperCase());
20
-
21
- formatted = formatted.replace(/\s+/g, ' ').trim();
22
-
23
- return formatted || 'Query details';
24
- }
@@ -1,94 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import { X } from 'lucide-react';
3
- import thinking from '../../shadcn/components/icons/thinking.gif';
4
-
5
- type QueryLoadingModalProps = {
6
- isOpen: boolean;
7
- onClose: () => void;
8
- }
9
-
10
- export function QueryLoadingModal({ isOpen, onClose }: QueryLoadingModalProps) {
11
-
12
-
13
- useEffect(() => {
14
- function handleEscapeKey(event: KeyboardEvent) {
15
- if (event.key === 'Escape' && isOpen) {
16
- onClose();
17
- }
18
- }
19
-
20
- if (isOpen) {
21
- document.addEventListener('keydown', handleEscapeKey);
22
- document.body.style.overflow = 'hidden';
23
- }
24
-
25
- return () => {
26
- document.removeEventListener('keydown', handleEscapeKey);
27
- document.body.style.overflow = 'unset';
28
- };
29
- }, [isOpen, onClose]);
30
-
31
- function handleBackdropClick(event: React.MouseEvent<HTMLDivElement>) {
32
- if (event.target === event.currentTarget) {
33
- onClose();
34
- }
35
- }
36
-
37
- if (!isOpen) {
38
- return null;
39
- }
40
-
41
- return (
42
- <div
43
- className="fixed inset-0 z-[9999] flex items-center justify-center p-4"
44
- style={{ backgroundColor: 'rgba(0, 0, 0, 0.3)' }}
45
- onClick={handleBackdropClick}
46
- >
47
- <div
48
- className="relative bg-white rounded-[16px] shadow-[0px_8px_16px_-4px_rgba(0,0,0,0.1)] w-[481px] h-[258px] flex items-center justify-center p-6"
49
- onClick={(e) => e.stopPropagation()}
50
- >
51
- <button
52
- onClick={onClose}
53
- className="absolute top-4 right-4 transition-colors duration-200 hover:bg-gray-100 rounded p-1 flex items-center justify-center"
54
- type="button"
55
- aria-label="Close modal"
56
- style={{
57
- width: '24px',
58
- height: '24px'
59
- }}
60
- >
61
- <X
62
- size={12}
63
- className="text-gray-600"
64
- style={{
65
- opacity: 1,
66
- transform: 'rotate(0deg)'
67
- }}
68
- />
69
- </button>
70
- <div className="flex flex-col items-center space-y-4">
71
- <div
72
- className="flex flex-col justify-center items-center"
73
- style={{ margin: '16px', gap: '16px' }}
74
- >
75
- <img
76
- src={thinking}
77
- alt="Thinking..."
78
- style={{
79
- width: '24px',
80
- height: '24px'
81
- }}
82
- />
83
- </div>
84
- <h3 className="text-xl font-semibold text-[#020D21]">
85
- Thinking...
86
- </h3>
87
- <p className="text-base font-medium text-[#687387]">
88
- Generating query for this component
89
- </p>
90
- </div>
91
- </div>
92
- </div>
93
- );
94
- }