@peak-ai/canvas 1.4.22 → 1.4.23

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 (209) hide show
  1. package/package.json +7 -45
  2. package/.babelrc +0 -14
  3. package/.eslintcache +0 -1
  4. package/.eslintignore +0 -5
  5. package/.eslintrc.js +0 -29
  6. package/dist/package.json +0 -62
  7. package/scripts/build.ts +0 -120
  8. package/src/GrapesjsCanvas.tsx +0 -494
  9. package/src/constants/index.ts +0 -25
  10. package/src/declaration.d.ts +0 -1
  11. package/src/helpers/compiled-table.css +0 -2429
  12. package/src/helpers/css.ts +0 -2667
  13. package/src/helpers/date-picker.ts +0 -807
  14. package/src/helpers/filter-placeholder.ts +0 -18
  15. package/src/helpers/index.ts +0 -13
  16. package/src/helpers/merge-json.ts +0 -106
  17. package/src/index.styles.ts +0 -58
  18. package/src/index.ts +0 -9
  19. package/src/plugins/grapejs-plugin.tsx +0 -196
  20. package/src/plugins/helpers/custom-modal.tsx +0 -123
  21. package/src/plugins/helpers/data-table.tsx +0 -300
  22. package/src/plugins/helpers/extra.tsx +0 -164
  23. package/src/plugins/helpers/query-cache-context.tsx +0 -154
  24. package/src/plugins/helpers/query-cache-singleton.ts +0 -176
  25. package/src/plugins/helpers/query-cache-utils.ts +0 -226
  26. package/src/plugins/helpers/query-details-modal.tsx +0 -400
  27. package/src/plugins/helpers/query-heading-formatter.ts +0 -24
  28. package/src/plugins/helpers/query-loading-modal.tsx +0 -94
  29. package/src/plugins/helpers/render-components.tsx +0 -1450
  30. package/src/plugins/helpers/styled-info-button.tsx +0 -504
  31. package/src/public/canvas.css +0 -42
  32. package/src/public/components-css/table/table-output.css +0 -2436
  33. package/src/public/components-css/table/table.css +0 -30
  34. package/src/public/output.css +0 -2465
  35. package/src/public/table.css +0 -135
  36. package/src/shadcn/components/icons/AiAvatarIcon.tsx +0 -47
  37. package/src/shadcn/components/icons/Co_driver Expanding button copy.svg +0 -21
  38. package/src/shadcn/components/icons/ai-avatar.svg +0 -7
  39. package/src/shadcn/components/icons/thinking.gif +0 -0
  40. package/src/shadcn/components/ui/button.tsx +0 -132
  41. package/src/shadcn/components/ui/card.tsx +0 -92
  42. package/src/shadcn/components/ui/chart.tsx +0 -324
  43. package/src/shadcn/components/ui/checkbox.tsx +0 -27
  44. package/src/shadcn/components/ui/component-wrapper.tsx +0 -61
  45. package/src/shadcn/components/ui/date-filter.tsx +0 -816
  46. package/src/shadcn/components/ui/error-container.tsx +0 -125
  47. package/src/shadcn/components/ui/error-wrapper.tsx +0 -99
  48. package/src/shadcn/components/ui/filter.tsx +0 -368
  49. package/src/shadcn/components/ui/hover-card.tsx +0 -36
  50. package/src/shadcn/components/ui/input.tsx +0 -20
  51. package/src/shadcn/components/ui/label.tsx +0 -24
  52. package/src/shadcn/components/ui/pagination.tsx +0 -213
  53. package/src/shadcn/components/ui/scroll-area.tsx +0 -59
  54. package/src/shadcn/components/ui/search.tsx +0 -150
  55. package/src/shadcn/components/ui/separator.tsx +0 -26
  56. package/src/shadcn/components/ui/skeleton.tsx +0 -69
  57. package/src/shadcn/components/ui/table.tsx +0 -196
  58. package/src/shadcn/components/ui/tabs.tsx +0 -55
  59. package/src/shadcn/components/ui/textarea.tsx +0 -18
  60. package/src/shadcn/components/ui/tooltip.tsx +0 -87
  61. package/src/shadcn/utils.ts +0 -6
  62. package/src/types/grapesjs-tailwind.d.ts +0 -61
  63. package/src/types/images.d.ts +0 -1
  64. package/tailwind.config.js +0 -5
  65. package/tooling/tailwind-compiler/index.js +0 -99
  66. package/tooling/tailwind-compiler/package.json +0 -11
  67. package/tooling/tailwind-compiler/yarn.lock +0 -123
  68. package/tsconfig.build.json +0 -15
  69. package/tsconfig.json +0 -8
  70. /package/{dist/GrapesjsCanvas.d.ts → GrapesjsCanvas.d.ts} +0 -0
  71. /package/{dist/GrapesjsCanvas.js → GrapesjsCanvas.js} +0 -0
  72. /package/{dist/GrapesjsCanvas.js.map → GrapesjsCanvas.js.map} +0 -0
  73. /package/{dist/constants → constants}/index.d.ts +0 -0
  74. /package/{dist/constants → constants}/index.js +0 -0
  75. /package/{dist/constants → constants}/index.js.map +0 -0
  76. /package/{dist/declaration.d.js → declaration.d.js} +0 -0
  77. /package/{dist/declaration.d.js.map → declaration.d.js.map} +0 -0
  78. /package/{dist/helpers → helpers}/compiled-table.css +0 -0
  79. /package/{dist/helpers → helpers}/css.d.ts +0 -0
  80. /package/{dist/helpers → helpers}/css.js +0 -0
  81. /package/{dist/helpers → helpers}/css.js.map +0 -0
  82. /package/{dist/helpers → helpers}/date-picker.d.ts +0 -0
  83. /package/{dist/helpers → helpers}/date-picker.js +0 -0
  84. /package/{dist/helpers → helpers}/date-picker.js.map +0 -0
  85. /package/{dist/helpers → helpers}/filter-placeholder.d.ts +0 -0
  86. /package/{dist/helpers → helpers}/filter-placeholder.js +0 -0
  87. /package/{dist/helpers → helpers}/filter-placeholder.js.map +0 -0
  88. /package/{dist/helpers → helpers}/index.d.ts +0 -0
  89. /package/{dist/helpers → helpers}/index.js +0 -0
  90. /package/{dist/helpers → helpers}/index.js.map +0 -0
  91. /package/{dist/helpers → helpers}/merge-json.d.ts +0 -0
  92. /package/{dist/helpers → helpers}/merge-json.js +0 -0
  93. /package/{dist/helpers → helpers}/merge-json.js.map +0 -0
  94. /package/{dist/index.d.ts → index.d.ts} +0 -0
  95. /package/{dist/index.js → index.js} +0 -0
  96. /package/{dist/index.js.map → index.js.map} +0 -0
  97. /package/{dist/index.styles.d.ts → index.styles.d.ts} +0 -0
  98. /package/{dist/index.styles.js → index.styles.js} +0 -0
  99. /package/{dist/index.styles.js.map → index.styles.js.map} +0 -0
  100. /package/{dist/plugins → plugins}/grapejs-plugin.d.ts +0 -0
  101. /package/{dist/plugins → plugins}/grapejs-plugin.js +0 -0
  102. /package/{dist/plugins → plugins}/grapejs-plugin.js.map +0 -0
  103. /package/{dist/plugins → plugins}/helpers/custom-modal.d.ts +0 -0
  104. /package/{dist/plugins → plugins}/helpers/custom-modal.js +0 -0
  105. /package/{dist/plugins → plugins}/helpers/custom-modal.js.map +0 -0
  106. /package/{dist/plugins → plugins}/helpers/data-table.d.ts +0 -0
  107. /package/{dist/plugins → plugins}/helpers/data-table.js +0 -0
  108. /package/{dist/plugins → plugins}/helpers/data-table.js.map +0 -0
  109. /package/{dist/plugins → plugins}/helpers/extra.d.ts +0 -0
  110. /package/{dist/plugins → plugins}/helpers/extra.js +0 -0
  111. /package/{dist/plugins → plugins}/helpers/extra.js.map +0 -0
  112. /package/{dist/plugins → plugins}/helpers/query-cache-context.d.ts +0 -0
  113. /package/{dist/plugins → plugins}/helpers/query-cache-context.js +0 -0
  114. /package/{dist/plugins → plugins}/helpers/query-cache-context.js.map +0 -0
  115. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.d.ts +0 -0
  116. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.js +0 -0
  117. /package/{dist/plugins → plugins}/helpers/query-cache-singleton.js.map +0 -0
  118. /package/{dist/plugins → plugins}/helpers/query-cache-utils.d.ts +0 -0
  119. /package/{dist/plugins → plugins}/helpers/query-cache-utils.js +0 -0
  120. /package/{dist/plugins → plugins}/helpers/query-cache-utils.js.map +0 -0
  121. /package/{dist/plugins → plugins}/helpers/query-details-modal.d.ts +0 -0
  122. /package/{dist/plugins → plugins}/helpers/query-details-modal.js +0 -0
  123. /package/{dist/plugins → plugins}/helpers/query-details-modal.js.map +0 -0
  124. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.d.ts +0 -0
  125. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.js +0 -0
  126. /package/{dist/plugins → plugins}/helpers/query-heading-formatter.js.map +0 -0
  127. /package/{dist/plugins → plugins}/helpers/query-loading-modal.d.ts +0 -0
  128. /package/{dist/plugins → plugins}/helpers/query-loading-modal.js +0 -0
  129. /package/{dist/plugins → plugins}/helpers/query-loading-modal.js.map +0 -0
  130. /package/{dist/plugins → plugins}/helpers/render-components.d.ts +0 -0
  131. /package/{dist/plugins → plugins}/helpers/render-components.js +0 -0
  132. /package/{dist/plugins → plugins}/helpers/render-components.js.map +0 -0
  133. /package/{dist/plugins → plugins}/helpers/styled-info-button.d.ts +0 -0
  134. /package/{dist/plugins → plugins}/helpers/styled-info-button.js +0 -0
  135. /package/{dist/plugins → plugins}/helpers/styled-info-button.js.map +0 -0
  136. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.d.ts +0 -0
  137. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.js +0 -0
  138. /package/{dist/shadcn → shadcn}/components/icons/AiAvatarIcon.js.map +0 -0
  139. /package/{dist/shadcn → shadcn}/components/icons/thinking.gif +0 -0
  140. /package/{dist/shadcn → shadcn}/components/ui/button.d.ts +0 -0
  141. /package/{dist/shadcn → shadcn}/components/ui/button.js +0 -0
  142. /package/{dist/shadcn → shadcn}/components/ui/button.js.map +0 -0
  143. /package/{dist/shadcn → shadcn}/components/ui/card.d.ts +0 -0
  144. /package/{dist/shadcn → shadcn}/components/ui/card.js +0 -0
  145. /package/{dist/shadcn → shadcn}/components/ui/card.js.map +0 -0
  146. /package/{dist/shadcn → shadcn}/components/ui/chart.d.ts +0 -0
  147. /package/{dist/shadcn → shadcn}/components/ui/chart.js +0 -0
  148. /package/{dist/shadcn → shadcn}/components/ui/chart.js.map +0 -0
  149. /package/{dist/shadcn → shadcn}/components/ui/checkbox.d.ts +0 -0
  150. /package/{dist/shadcn → shadcn}/components/ui/checkbox.js +0 -0
  151. /package/{dist/shadcn → shadcn}/components/ui/checkbox.js.map +0 -0
  152. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.d.ts +0 -0
  153. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.js +0 -0
  154. /package/{dist/shadcn → shadcn}/components/ui/component-wrapper.js.map +0 -0
  155. /package/{dist/shadcn → shadcn}/components/ui/date-filter.d.ts +0 -0
  156. /package/{dist/shadcn → shadcn}/components/ui/date-filter.js +0 -0
  157. /package/{dist/shadcn → shadcn}/components/ui/date-filter.js.map +0 -0
  158. /package/{dist/shadcn → shadcn}/components/ui/error-container.d.ts +0 -0
  159. /package/{dist/shadcn → shadcn}/components/ui/error-container.js +0 -0
  160. /package/{dist/shadcn → shadcn}/components/ui/error-container.js.map +0 -0
  161. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.d.ts +0 -0
  162. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.js +0 -0
  163. /package/{dist/shadcn → shadcn}/components/ui/error-wrapper.js.map +0 -0
  164. /package/{dist/shadcn → shadcn}/components/ui/filter.d.ts +0 -0
  165. /package/{dist/shadcn → shadcn}/components/ui/filter.js +0 -0
  166. /package/{dist/shadcn → shadcn}/components/ui/filter.js.map +0 -0
  167. /package/{dist/shadcn → shadcn}/components/ui/hover-card.d.ts +0 -0
  168. /package/{dist/shadcn → shadcn}/components/ui/hover-card.js +0 -0
  169. /package/{dist/shadcn → shadcn}/components/ui/hover-card.js.map +0 -0
  170. /package/{dist/shadcn → shadcn}/components/ui/input.d.ts +0 -0
  171. /package/{dist/shadcn → shadcn}/components/ui/input.js +0 -0
  172. /package/{dist/shadcn → shadcn}/components/ui/input.js.map +0 -0
  173. /package/{dist/shadcn → shadcn}/components/ui/label.d.ts +0 -0
  174. /package/{dist/shadcn → shadcn}/components/ui/label.js +0 -0
  175. /package/{dist/shadcn → shadcn}/components/ui/label.js.map +0 -0
  176. /package/{dist/shadcn → shadcn}/components/ui/pagination.d.ts +0 -0
  177. /package/{dist/shadcn → shadcn}/components/ui/pagination.js +0 -0
  178. /package/{dist/shadcn → shadcn}/components/ui/pagination.js.map +0 -0
  179. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.d.ts +0 -0
  180. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.js +0 -0
  181. /package/{dist/shadcn → shadcn}/components/ui/scroll-area.js.map +0 -0
  182. /package/{dist/shadcn → shadcn}/components/ui/search.d.ts +0 -0
  183. /package/{dist/shadcn → shadcn}/components/ui/search.js +0 -0
  184. /package/{dist/shadcn → shadcn}/components/ui/search.js.map +0 -0
  185. /package/{dist/shadcn → shadcn}/components/ui/separator.d.ts +0 -0
  186. /package/{dist/shadcn → shadcn}/components/ui/separator.js +0 -0
  187. /package/{dist/shadcn → shadcn}/components/ui/separator.js.map +0 -0
  188. /package/{dist/shadcn → shadcn}/components/ui/skeleton.d.ts +0 -0
  189. /package/{dist/shadcn → shadcn}/components/ui/skeleton.js +0 -0
  190. /package/{dist/shadcn → shadcn}/components/ui/skeleton.js.map +0 -0
  191. /package/{dist/shadcn → shadcn}/components/ui/table.d.ts +0 -0
  192. /package/{dist/shadcn → shadcn}/components/ui/table.js +0 -0
  193. /package/{dist/shadcn → shadcn}/components/ui/table.js.map +0 -0
  194. /package/{dist/shadcn → shadcn}/components/ui/tabs.d.ts +0 -0
  195. /package/{dist/shadcn → shadcn}/components/ui/tabs.js +0 -0
  196. /package/{dist/shadcn → shadcn}/components/ui/tabs.js.map +0 -0
  197. /package/{dist/shadcn → shadcn}/components/ui/textarea.d.ts +0 -0
  198. /package/{dist/shadcn → shadcn}/components/ui/textarea.js +0 -0
  199. /package/{dist/shadcn → shadcn}/components/ui/textarea.js.map +0 -0
  200. /package/{dist/shadcn → shadcn}/components/ui/tooltip.d.ts +0 -0
  201. /package/{dist/shadcn → shadcn}/components/ui/tooltip.js +0 -0
  202. /package/{dist/shadcn → shadcn}/components/ui/tooltip.js.map +0 -0
  203. /package/{dist/shadcn → shadcn}/utils.d.ts +0 -0
  204. /package/{dist/shadcn → shadcn}/utils.js +0 -0
  205. /package/{dist/shadcn → shadcn}/utils.js.map +0 -0
  206. /package/{dist/types → types}/grapesjs-tailwind.d.js +0 -0
  207. /package/{dist/types → types}/grapesjs-tailwind.d.js.map +0 -0
  208. /package/{dist/types → types}/images.d.js +0 -0
  209. /package/{dist/types → types}/images.d.js.map +0 -0
@@ -1,125 +0,0 @@
1
- import styled from 'styled-components';
2
-
3
- type Size = 'small' | 'medium' | 'large';
4
-
5
- export const ErrorContainer = styled.div<{ hasError: boolean }>`
6
- position: relative;
7
- width: 100%;
8
- height: 100%;
9
- border: ${({ hasError }) => (hasError ? '2px solid #ef4444' : 'none')};
10
- border-radius: 6px;
11
- overflow: hidden;
12
- animation: ${({ hasError }) => (hasError ? 'errorShake 0.5s ease-in-out' : 'none')};
13
-
14
- @keyframes errorShake {
15
- 0%, 100% { transform: translateX(0); }
16
- 25% { transform: translateX(-2px); }
17
- 75% { transform: translateX(2px); }
18
- }
19
- `;
20
-
21
- export const ErrorBanner = styled.div<{ size: Size }>`
22
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
23
- color: white;
24
- display: flex;
25
- align-items: center;
26
- gap: 8px;
27
- font-weight: 500;
28
- position: ${({ size }) => (size === 'small' ? 'absolute' : 'relative')};
29
- top: ${({ size }) => (size === 'small' ? '4px' : 'auto')};
30
- left: ${({ size }) => (size === 'small' ? '4px' : 'auto')};
31
- right: ${({ size }) => (size === 'small' ? '4px' : 'auto')};
32
- z-index: ${({ size }) => (size === 'small' ? 10 : 'auto')};
33
- transform: ${({ size }) => (size === 'small' ? 'scale(0.8)' : 'none')};
34
- transform-origin: top left;
35
- max-width: ${({ size }) => (size === 'small' ? '90%' : '100%')};
36
- border-radius: ${({ size }) => (size === 'small' ? '4px' : '0')};
37
- box-shadow: ${({ size }) =>
38
- size === 'small' ? '0 2px 4px rgba(0, 0, 0, 0.2)' : 'none'};
39
-
40
- padding: ${({ size }) => {
41
- switch (size) {
42
- case 'small': return '4px 8px';
43
- case 'medium': return '6px 10px';
44
- case 'large': return '8px 12px';
45
- default: return '6px 10px';
46
- }
47
- }};
48
-
49
- font-size: ${({ size }) => {
50
- switch (size) {
51
- case 'small': return '10px';
52
- case 'medium': return '11px';
53
- case 'large': return '12px';
54
- default: return '11px';
55
- }
56
- }};
57
- `;
58
-
59
- export const ErrorIcon = styled.div<{ size: Size }>`
60
- font-size: ${({ size }) => {
61
- switch (size) {
62
- case 'small': return '12px';
63
- case 'medium': return '13px';
64
- case 'large': return '14px';
65
- default: return '13px';
66
- }
67
- }};
68
- flex-shrink: 0;
69
- `;
70
-
71
- export const ErrorContent = styled.div`
72
- flex: 1;
73
- min-width: 0;
74
- `;
75
-
76
- export const ErrorMessage = styled.div<{ size: Size }>`
77
- font-weight: 600;
78
- white-space: nowrap;
79
- overflow: hidden;
80
- text-overflow: ellipsis;
81
- margin-bottom: ${({ size }) => (size === 'small' ? '0' : '1px')};
82
- `;
83
-
84
- export const ErrorType = styled.div<{ size: Size }>`
85
- opacity: 0.9;
86
- font-size: ${({ size }) => {
87
- switch (size) {
88
- case 'small': return '9px';
89
- case 'medium': return '10px';
90
- case 'large': return '11px';
91
- default: return '10px';
92
- }
93
- }};
94
- text-transform: uppercase;
95
- letter-spacing: ${({ size }) => (size === 'small' ? '0.2px' : '0.3px')};
96
- `;
97
-
98
- export const ComponentContent = styled.div<{ hasError: boolean; size: Size }>`
99
- flex: 1;
100
- background: ${({ hasError }) =>
101
- hasError ? 'rgba(239, 68, 68, 0.05)' : 'transparent'};
102
-
103
- padding: ${({ hasError, size }) => {
104
- if (!hasError) {return '0';}
105
-
106
- switch (size) {
107
- case 'small': return '4px';
108
- case 'medium': return '6px';
109
- case 'large': return '8px';
110
- default: return '6px';
111
- }
112
- }};
113
-
114
- padding-top: ${({ hasError, size }) => {
115
- if (!hasError) {return '0';}
116
-
117
- return size === 'small' ? '20px' : '8px';
118
- }};
119
-
120
- min-height: ${({ hasError, size }) =>
121
- hasError && size === 'small' ? '60px' : 'auto'};
122
-
123
- display: flex;
124
- flex-direction: column;
125
- `;
@@ -1,99 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import React, { useEffect, useState } from 'react';
3
- import { CircleAlert } from 'lucide-react';
4
-
5
- type IssueInfo = {
6
- message: string;
7
- type?: string;
8
- };
9
-
10
- type ComponentProps = {
11
- error?: IssueInfo;
12
- isMissing?: boolean;
13
- componentType?: string;
14
- gjsModel?: any;
15
- onDismissMissing?: (componentId: string) => void;
16
- [key: string]: unknown;
17
- };
18
-
19
- type ComponentWrapperProps = {
20
- children: React.ReactNode;
21
- componentProps: ComponentProps;
22
- className?: string;
23
- };
24
-
25
- function renderNoDataFallback() {
26
- return (
27
- <div
28
- className="w-full py-8 flex flex-col items-center justify-center px-6 text-center"
29
- style={{ minHeight: '180px' }}
30
- >
31
- <CircleAlert className="w-12 h-12 text-gray-400 mb-2" />
32
- <h3 className="text-lg font-medium text-gray-900">No data available</h3>
33
- <p className="mt-2 text-sm text-gray-500 max-w-md">
34
- Check your filters or try a different time range.
35
- </p>
36
- </div>
37
- );
38
- }
39
-
40
- const COMPONENTS_WITH_CUSTOM_ERROR_HANDLING = new Set([
41
- 'Actions',
42
- 'ActionCard',
43
- 'Card',
44
- 'Chart',
45
- 'Markdown',
46
- 'Table',
47
- 'Tabs',
48
- ]);
49
-
50
- export function ComponentWrapper({
51
- children,
52
- componentProps,
53
- className = '',
54
- }: ComponentWrapperProps) {
55
- const { gjsModel, componentType } = componentProps;
56
-
57
- const [currentProps, setCurrentProps] = useState(componentProps);
58
- const [currentAttributes, setCurrentAttributes] = useState(gjsModel?.get('attributes') || {});
59
-
60
- function handlePropsChange(model: any) {
61
- const updatedModelProps = model.get('componentProps');
62
- setCurrentProps({
63
- ...componentProps,
64
- ...updatedModelProps,
65
- });
66
- }
67
-
68
- function handleAttributesChange(model: any) {
69
- const updatedAttributes = model.get('attributes');
70
- setCurrentAttributes(updatedAttributes);
71
- }
72
-
73
- useEffect(() => {
74
- if (gjsModel) {
75
- gjsModel.on('change:componentProps', () => handlePropsChange(gjsModel));
76
- gjsModel.on('change:attributes', () => handleAttributesChange(gjsModel));
77
-
78
- return () => {
79
- gjsModel.off('change:componentProps', () => handlePropsChange(gjsModel));
80
- gjsModel.off('change:attributes', () => handleAttributesChange(gjsModel));
81
- };
82
- }
83
-
84
- return undefined;
85
- }, [gjsModel, componentProps, componentType]);
86
-
87
- const error = currentAttributes.error || currentProps.error;
88
- const isMissing = currentAttributes.isMissing || currentProps.isMissing;
89
-
90
- const hasCustomErrorHandling =
91
- componentType && COMPONENTS_WITH_CUSTOM_ERROR_HANDLING.has(componentType);
92
- const shouldShowWrapperFallback = !hasCustomErrorHandling && (isMissing || error);
93
-
94
- if (shouldShowWrapperFallback) {
95
- return <div className={className}>{renderNoDataFallback()}</div>;
96
- }
97
-
98
- return <>{children}</>;
99
- }
@@ -1,368 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { ChevronDown, ChevronUp, ListFilter as FilterIcon, Loader2Icon } from 'lucide-react';
4
-
5
- import { Button } from './button';
6
- import { Checkbox } from './checkbox';
7
- import { ScrollArea } from './scroll-area';
8
- import { getAffectedComponentsWithLoader } from '../../../helpers';
9
- import { renderDateFilter } from './date-filter';
10
-
11
- type FilterOption = {
12
- label: string;
13
- value: string;
14
- };
15
-
16
- type FilterProps = {
17
- isEditable?: boolean;
18
- gjsModel: any;
19
- performInteraction: (payload: Record<string, any>) => Promise<void>;
20
- };
21
-
22
- type FilterHeaderProps = {
23
- label: string;
24
- count: number;
25
- isDisabled: boolean;
26
- isDropdownOpen: boolean;
27
- isLoading: boolean;
28
- toggleOpen: () => void;
29
- };
30
-
31
- type FilterActionsProps = {
32
- selected: string[];
33
- allSelected: boolean;
34
- onClear: () => void;
35
- onSelectAll: () => void;
36
- isDisabled: boolean;
37
- };
38
-
39
- type FilterOptionListProps = {
40
- options: FilterOption[];
41
- selected: string[];
42
- onToggle: (value: string) => void;
43
- isDisabled: boolean;
44
- };
45
-
46
- function FilterHeader({
47
- label,
48
- count,
49
- isDisabled,
50
- isDropdownOpen,
51
- isLoading,
52
- toggleOpen,
53
- }: FilterHeaderProps) {
54
- const ChevronIcon = isDropdownOpen ? ChevronUp : ChevronDown;
55
-
56
- return (
57
- <Button variant="outline" size="sm" disabled={isDisabled} onClick={toggleOpen} className="px-2">
58
- <FilterIcon size={16} />
59
- {count > 0 ? `${label} (${count})` : label}
60
- {isLoading ? (
61
- <Loader2Icon className="ml-2 animate-spin" size={16} />
62
- ) : (
63
- <ChevronIcon size={16} className="ml-1" />
64
- )}
65
- </Button>
66
- );
67
- }
68
-
69
- function FilterActions({
70
- selected,
71
- allSelected,
72
- onClear,
73
- onSelectAll,
74
- isDisabled,
75
- }: FilterActionsProps) {
76
- return (
77
- <div className="flex items-center mb-3">
78
- <Checkbox
79
- checked={allSelected}
80
- onCheckedChange={() => (allSelected ? onClear() : onSelectAll())}
81
- disabled={isDisabled}
82
- />
83
- <span className="ml-2 text-sm text-gray-900">Select All</span>
84
- {selected.length > 0 && (
85
- <button
86
- type="button"
87
- className="ml-auto text-sm text-blue-600 hover:underline"
88
- onMouseDown={(e) => {
89
- e.stopPropagation();
90
- e.preventDefault();
91
- }}
92
- onClick={onClear}
93
- disabled={isDisabled}
94
- >
95
- Clear All
96
- </button>
97
- )}
98
- </div>
99
- );
100
- }
101
-
102
- function FilterOptionList({ options, selected, onToggle, isDisabled }: FilterOptionListProps) {
103
- return (
104
- <ScrollArea viewportClassName="max-h-48 overflow-y-auto mb-4 space-y-2">
105
- {options.length > 0 ? (
106
- options.map((opt) => (
107
- <label
108
- key={opt.value}
109
- className="flex items-center space-x-2 hover:bg-gray-100 rounded p-1 transition hover:cursor-pointer"
110
- onClick={(e) => {
111
- e.preventDefault();
112
- e.stopPropagation();
113
-
114
- if (!isDisabled) {
115
- onToggle(opt.value);
116
- }
117
- }}
118
- >
119
- <Checkbox
120
- checked={selected.includes(opt.value)}
121
- onChange={() => {
122
- // Prevent checkbox from toggling when clicking label
123
- }}
124
- disabled={isDisabled}
125
- />
126
- <span className="text-sm text-gray-900">{opt.label}</span>
127
- </label>
128
- ))
129
- ) : (
130
- <div className="text-sm text-gray-500">No results found</div>
131
- )}
132
- </ScrollArea>
133
- );
134
- }
135
-
136
- export function renderFilter({ gjsModel, performInteraction }: FilterProps) {
137
- const [componentData, setComponentData] = useState({ ...gjsModel.get('componentProps') });
138
-
139
- const {
140
- options = [],
141
- value = [],
142
- className = '',
143
- affectedComponents = [],
144
- text: label = 'Filter',
145
- filterType = 'multiselect',
146
- } = componentData;
147
-
148
- const actualOptions = (() => {
149
- if (options && typeof options === 'object' && options.name === '__peak_placeholder') {
150
- return [];
151
- }
152
-
153
- return Array.isArray(options) ? options : [];
154
- })();
155
-
156
- if (filterType === 'date') {
157
- return renderDateFilter({ gjsModel, performInteraction });
158
- }
159
-
160
- const wrapperRef = useRef<HTMLDivElement>(null);
161
-
162
- const [attributes, setAttributes] = useState({ ...gjsModel.get('attributes') });
163
- const [isDropdownOpen, setIsDropdownOpen] = useState(false);
164
- const [searchQuery, setSearchQuery] = useState('');
165
- const [isApplying, setIsApplying] = useState(false);
166
- const [dropdownPosition, setDropdownPosition] = useState({ left: 'auto', right: '0' });
167
-
168
- const defaultValue = componentData.default || [];
169
-
170
- const [selectedValues, setSelectedValues] = useState<string[]>(() => {
171
- return Array.isArray(value) && value.length > 0 ? value : defaultValue;
172
- });
173
-
174
- const isMultiSelect = filterType === 'multiselect';
175
- const hasPlaceholderOptions = options && typeof options === 'object' && options.name === '__peak_placeholder';
176
- const hasError = attributes.error || componentData.error;
177
- const isLoading = !hasError && (attributes.interactionApiInProgress || isApplying || attributes.loading || hasPlaceholderOptions);
178
- const isBusy = isLoading || hasError;
179
- const allOptionsSelected = selectedValues.length === actualOptions.length && actualOptions.length > 0;
180
-
181
- useEffect(() => {
182
- if (!isDropdownOpen || !wrapperRef.current) {return;}
183
-
184
- const filterRect = wrapperRef.current.getBoundingClientRect();
185
- const dropdownWidth = 256;
186
- const iframeViewportWidth = document.documentElement.clientWidth;
187
- const iframeBodyWidth =
188
- document.getElementById('dashboard-root')?.clientWidth || iframeViewportWidth;
189
-
190
- const spaceToRight = iframeBodyWidth - filterRect.right;
191
- const spaceToLeft = filterRect.left;
192
-
193
- if (spaceToLeft >= dropdownWidth) {
194
- setDropdownPosition({ left: 'auto', right: '0px' });
195
- } else if (spaceToRight < dropdownWidth && spaceToLeft < dropdownWidth) {
196
- const shiftLeft = dropdownWidth - spaceToRight + 16;
197
- setDropdownPosition({ left: `-${shiftLeft}px`, right: 'auto' });
198
- } else if (spaceToRight >= dropdownWidth) {
199
- setDropdownPosition({ left: '0px', right: 'auto' });
200
- }
201
- }, [isDropdownOpen]);
202
-
203
- useEffect(() => {
204
- function updateComponentData() {
205
- setComponentData({ ...gjsModel.get('componentProps') });
206
- }
207
-
208
- function updateAttributes() {
209
- setAttributes({ ...gjsModel.get('attributes') });
210
- }
211
-
212
- gjsModel.on('change:componentProps', updateComponentData);
213
- gjsModel.on('change:attributes', updateAttributes);
214
-
215
- return () => {
216
- gjsModel.off('change:componentProps', updateComponentData);
217
- gjsModel.off('change:attributes', updateAttributes);
218
- };
219
- }, [gjsModel]);
220
-
221
- useEffect(() => {
222
- const doc = wrapperRef.current?.ownerDocument ?? document;
223
-
224
- function handleOutsideClick(e: PointerEvent) {
225
- if (isDropdownOpen && wrapperRef.current && !wrapperRef.current.contains(e.target as Node)) {
226
- setIsDropdownOpen(false);
227
- }
228
- }
229
-
230
- function handleEscape(e: KeyboardEvent) {
231
- if (e.key === 'Escape') {
232
- setIsDropdownOpen(false);
233
- }
234
- }
235
-
236
- doc.addEventListener('pointerdown', handleOutsideClick);
237
- doc.addEventListener('keydown', handleEscape);
238
-
239
- return () => {
240
- doc.removeEventListener('pointerdown', handleOutsideClick);
241
- doc.removeEventListener('keydown', handleEscape);
242
- };
243
- }, [isDropdownOpen]);
244
-
245
- const filteredOptions = actualOptions.filter((opt: FilterOption) =>
246
- String(opt.label).toLowerCase().includes(searchQuery.toLowerCase()),
247
- );
248
-
249
- async function updateAndApply(newValues: string[] = selectedValues) {
250
- setIsApplying(true);
251
-
252
- try {
253
- gjsModel.set('componentProps', {
254
- ...gjsModel.get('componentProps'),
255
- value: newValues,
256
- });
257
-
258
- const id = gjsModel.get('id');
259
-
260
- await performInteraction({
261
- interactionType: 'filter',
262
- id,
263
- affectedComponents: getAffectedComponentsWithLoader([id, ...affectedComponents], true),
264
- });
265
- } finally {
266
- setIsApplying(false);
267
- setIsDropdownOpen(false);
268
- }
269
- }
270
-
271
- const handleOptionToggle = useCallback(
272
- (val: string) => {
273
- if (isMultiSelect) {
274
- setSelectedValues((prev) =>
275
- prev.includes(val) ? prev.filter((v) => v !== val) : [...prev, val],
276
- );
277
- } else {
278
- if (selectedValues.includes(val)) {
279
- setSelectedValues([]);
280
- updateAndApply([]);
281
- } else {
282
- const singleValue = [val];
283
- setSelectedValues(singleValue);
284
- updateAndApply(singleValue);
285
- }
286
- }
287
- },
288
- [isMultiSelect, selectedValues],
289
- );
290
-
291
- function handleClearAll() {
292
- setSelectedValues([]);
293
- }
294
-
295
- function handleSelectAll() {
296
- setSelectedValues(actualOptions.map((o: FilterOption) => o.value));
297
- }
298
-
299
- return (
300
- <div
301
- ref={wrapperRef}
302
- className={`relative inline-block ${className}`}
303
- style={{ color: '#2A44D4', backgroundColor: 'rgb(255 255 255)' }}
304
- >
305
- <FilterHeader
306
- label={label}
307
- count={selectedValues.length}
308
- isDisabled={isBusy}
309
- isDropdownOpen={isDropdownOpen}
310
- isLoading={isLoading}
311
- toggleOpen={() => setIsDropdownOpen((prev) => !prev)}
312
- />
313
-
314
- {isDropdownOpen && (
315
- <div className="absolute top-full mt-2 w-64 bg-white border rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 p-4 z-50" style={dropdownPosition}>
316
- <input
317
- type="text"
318
- placeholder="Search..."
319
- value={searchQuery}
320
- onChange={(e) => setSearchQuery(e.target.value)}
321
- className="w-full mb-3 px-2 py-1 border rounded focus:outline-none"
322
- disabled={isBusy}
323
- />
324
-
325
- {isMultiSelect && (
326
- <FilterActions
327
- selected={selectedValues}
328
- allSelected={allOptionsSelected}
329
- onClear={handleClearAll}
330
- onSelectAll={handleSelectAll}
331
- isDisabled={isBusy}
332
- />
333
- )}
334
-
335
- <FilterOptionList
336
- options={filteredOptions}
337
- selected={selectedValues}
338
- onToggle={handleOptionToggle}
339
- isDisabled={isBusy}
340
- />
341
-
342
- {isMultiSelect && (
343
- <div className="flex justify-end space-x-2">
344
- <Button
345
- variant="ghost"
346
- size="sm"
347
- onClick={() => setIsDropdownOpen(false)}
348
- disabled={isApplying}
349
- className="bg-[#EAECFB] border border-[#2A44D4] text-[#263DBF] hover:bg-[#EAECFB] hover:text-[#263DBF]"
350
- >
351
- Cancel
352
- </Button>
353
- <Button
354
- variant="default"
355
- size="sm"
356
- onClick={() => updateAndApply(selectedValues)}
357
- disabled={isBusy}
358
- className="bg-[#2A44D4] text-white hover:bg-[#2A44D4] hover:text-white"
359
- >
360
- {isApplying && <Loader2Icon className="animate-spin mr-2" size={16} />}Apply
361
- </Button>
362
- </div>
363
- )}
364
- </div>
365
- )}
366
- </div>
367
- );
368
- }
@@ -1,36 +0,0 @@
1
- import * as React from 'react';
2
- import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
3
-
4
- import { cn } from '../../utils';
5
-
6
- function HoverCard({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
7
- return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
8
- }
9
-
10
- function HoverCardTrigger({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
11
- return <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />;
12
- }
13
-
14
- function HoverCardContent({
15
- className,
16
- align = 'center',
17
- sideOffset = 4,
18
- ...props
19
- }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
20
- return (
21
- <HoverCardPrimitive.Portal data-slot="hover-card-portal">
22
- <HoverCardPrimitive.Content
23
- data-slot="hover-card-content"
24
- align={align}
25
- sideOffset={sideOffset}
26
- className={cn(
27
- 'bg-popover text-popover-foreground 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',
28
- className,
29
- )}
30
- {...props}
31
- />
32
- </HoverCardPrimitive.Portal>
33
- );
34
- }
35
-
36
- export { HoverCard, HoverCardTrigger, HoverCardContent };
@@ -1,20 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { cn } from '../../utils';
4
-
5
- function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
6
- return (
7
- <input
8
- type={type}
9
- data-slot="input"
10
- className={cn(
11
- 'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
12
- 'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
13
- className,
14
- )}
15
- {...props}
16
- />
17
- );
18
- }
19
-
20
- export { Input };
@@ -1,24 +0,0 @@
1
- import * as React from 'react';
2
- import * as LabelPrimitive from '@radix-ui/react-label';
3
-
4
- import { cn } from '../../utils';
5
-
6
- function Label({
7
- className,
8
- isEditable,
9
- ...props
10
- }: React.ComponentProps<typeof LabelPrimitive.Root> & { isEditable?: boolean }) {
11
- return (
12
- <LabelPrimitive.Root
13
- data-slot="label"
14
- className={cn(
15
- 'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
16
- className,
17
- )}
18
- contentEditable={isEditable}
19
- {...props}
20
- />
21
- );
22
- }
23
-
24
- export { Label };