@kb-labs/studio-app 0.7.0 → 2.8.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 (175) hide show
  1. package/dist/index.html +1 -0
  2. package/dist/main.1d68e922.js +522 -0
  3. package/dist/main.1d68e922.js.map +1 -0
  4. package/dist/main.80b70197.css +2 -0
  5. package/dist/main.80b70197.css.map +1 -0
  6. package/dist/mf-manifest.json +241 -0
  7. package/dist/mf-stats.json +271 -0
  8. package/package.json +56 -39
  9. package/server.js +68 -0
  10. package/.env.example +0 -10
  11. package/UI-KIT-COMPONENTS.md +0 -783
  12. package/UI-KIT-PLAN.md +0 -326
  13. package/eslint-rules/no-direct-antd-import.js +0 -151
  14. package/eslint.config.ts +0 -27
  15. package/index.html +0 -17
  16. package/postcss.config.js +0 -7
  17. package/public/favicon.ico +0 -0
  18. package/rspack.config.mjs +0 -118
  19. package/src/App.tsx +0 -46
  20. package/src/components/devtools/devtools-log-feed.module.css +0 -165
  21. package/src/components/devtools/devtools-log-feed.tsx +0 -300
  22. package/src/components/devtools/devtools-panel.module.css +0 -121
  23. package/src/components/devtools/devtools-panel.tsx +0 -115
  24. package/src/components/empty-state.tsx +0 -28
  25. package/src/components/error-boundary.tsx +0 -210
  26. package/src/components/health-banner.module.css +0 -103
  27. package/src/components/health-banner.tsx +0 -134
  28. package/src/components/health-indicator.tsx +0 -12
  29. package/src/components/page-header.tsx +0 -49
  30. package/src/components/page-transition.tsx +0 -24
  31. package/src/components/role-switcher.tsx +0 -148
  32. package/src/components/run-badge.tsx +0 -13
  33. package/src/components/ui/icons.tsx +0 -509
  34. package/src/components/ui/index.ts +0 -25
  35. package/src/components/ui/kb-config-provider.tsx +0 -130
  36. package/src/components/ui/kb-header.module.css +0 -51
  37. package/src/components/ui/kb-header.tsx +0 -112
  38. package/src/components/ui/kb-notification-bell.module.css +0 -103
  39. package/src/components/ui/kb-notification-bell.tsx +0 -199
  40. package/src/components/ui/kb-page-layout.tsx +0 -66
  41. package/src/components/ui/kb-quick-search.module.css +0 -86
  42. package/src/components/ui/kb-quick-search.tsx +0 -196
  43. package/src/components/ui/kb-sidebar.module.css +0 -47
  44. package/src/components/ui/kb-sidebar.tsx +0 -196
  45. package/src/components/ui/kb-stat-card.module.css +0 -21
  46. package/src/components/ui/kb-stat-card.tsx +0 -22
  47. package/src/components/ui/kb-stat-grid.tsx +0 -22
  48. package/src/components/ui/kb-status-bar.module.css +0 -49
  49. package/src/components/ui/kb-status-bar.tsx +0 -145
  50. package/src/components/ui/kb-system-health-indicator.tsx +0 -229
  51. package/src/components/ui/kb-theme-toggle.tsx +0 -42
  52. package/src/components/ui/theme-adapter.ts +0 -812
  53. package/src/components/ui/theme-transition-overlay.tsx +0 -70
  54. package/src/components/ui/utils.ts +0 -6
  55. package/src/components/widget-error-boundary.tsx +0 -172
  56. package/src/config/env.ts +0 -5
  57. package/src/config/feature-flags.ts +0 -482
  58. package/src/config/studio.config.schema.ts +0 -88
  59. package/src/config/studio.config.ts +0 -84
  60. package/src/env.d.ts +0 -23
  61. package/src/hooks/use-command-palette.ts +0 -6
  62. package/src/hooks/use-devtools-store.ts +0 -25
  63. package/src/hooks/use-feature-flags.ts +0 -101
  64. package/src/index.css +0 -10
  65. package/src/layouts/dashboard-grid.tsx +0 -122
  66. package/src/layouts/index.ts +0 -12
  67. package/src/layouts/two-pane.tsx +0 -134
  68. package/src/main.tsx +0 -15
  69. package/src/modules/analytics/components/analytics-daily-stats-chart.tsx +0 -257
  70. package/src/modules/analytics/components/analytics-date-range-picker.tsx +0 -121
  71. package/src/modules/analytics/pages/analytics-cache-page.tsx +0 -285
  72. package/src/modules/analytics/pages/analytics-embeddings-page.tsx +0 -274
  73. package/src/modules/analytics/pages/analytics-events-page.tsx +0 -425
  74. package/src/modules/analytics/pages/analytics-llm-page.tsx +0 -434
  75. package/src/modules/analytics/pages/analytics-overview-page.tsx +0 -336
  76. package/src/modules/analytics/pages/analytics-page.tsx +0 -20
  77. package/src/modules/analytics/pages/analytics-storage-page.tsx +0 -344
  78. package/src/modules/analytics/pages/analytics-vectorstore-page.tsx +0 -279
  79. package/src/modules/analytics/routes/index.tsx +0 -133
  80. package/src/modules/analytics/utils/formatters.test.ts +0 -148
  81. package/src/modules/analytics/utils/formatters.ts +0 -100
  82. package/src/modules/auth/pages/login-page.module.css +0 -113
  83. package/src/modules/auth/pages/login-page.tsx +0 -80
  84. package/src/modules/auth/routes/index.tsx +0 -24
  85. package/src/modules/dashboard/components/ActivityTimelineWidget.tsx +0 -199
  86. package/src/modules/dashboard/components/AiInsightsWidget.tsx +0 -358
  87. package/src/modules/dashboard/components/AnimatedMetricCard.css +0 -88
  88. package/src/modules/dashboard/components/AnimatedMetricCard.tsx +0 -125
  89. package/src/modules/dashboard/components/HeroMetricCard.css +0 -114
  90. package/src/modules/dashboard/components/HeroMetricCard.tsx +0 -152
  91. package/src/modules/dashboard/components/HeroMetricsWidget.tsx +0 -146
  92. package/src/modules/dashboard/components/SystemResourcesWidget.tsx +0 -197
  93. package/src/modules/dashboard/components/dashboard-empty.tsx +0 -22
  94. package/src/modules/dashboard/components/dashboard-kpis-widget.tsx +0 -59
  95. package/src/modules/dashboard/components/dashboard-kpis.tsx +0 -13
  96. package/src/modules/dashboard/components/dashboard-latency-percentiles-widget.tsx +0 -85
  97. package/src/modules/dashboard/components/dashboard-metrics-widget.tsx +0 -78
  98. package/src/modules/dashboard/components/dashboard-plugins-widget.tsx +0 -67
  99. package/src/modules/dashboard/components/dashboard-requests-widget.tsx +0 -62
  100. package/src/modules/dashboard/layouts/dashboard-layout.tsx +0 -16
  101. package/src/modules/dashboard/pages/ai-insights-page.tsx +0 -563
  102. package/src/modules/dashboard/pages/dashboard-animations.css +0 -317
  103. package/src/modules/dashboard/pages/dashboard-page.tsx +0 -13
  104. package/src/modules/dashboard/routes/index.tsx +0 -70
  105. package/src/modules/observability/pages/devkit-page.tsx +0 -263
  106. package/src/modules/observability/pages/incident-detail-page.tsx +0 -571
  107. package/src/modules/observability/pages/incidents-page.tsx +0 -370
  108. package/src/modules/observability/pages/log-detail-page.tsx +0 -508
  109. package/src/modules/observability/pages/logs-page.tsx +0 -1129
  110. package/src/modules/observability/pages/prometheus-metrics-page.tsx +0 -486
  111. package/src/modules/observability/pages/state-broker-page.tsx +0 -229
  112. package/src/modules/observability/pages/system-events-page.tsx +0 -255
  113. package/src/modules/observability/routes/index.tsx +0 -133
  114. package/src/modules/plugins/components/marketplace-card.tsx +0 -153
  115. package/src/modules/plugins/components/plugin-ai-assistant-modal.tsx +0 -374
  116. package/src/modules/plugins/components/plugin-card.tsx +0 -136
  117. package/src/modules/plugins/components/plugin-detail/capabilities-summary.tsx +0 -101
  118. package/src/modules/plugins/components/plugin-detail/cli-commands-table.tsx +0 -101
  119. package/src/modules/plugins/components/plugin-detail/index.ts +0 -7
  120. package/src/modules/plugins/components/plugin-detail/jobs-table.tsx +0 -64
  121. package/src/modules/plugins/components/plugin-detail/permissions/env-permissions.tsx +0 -30
  122. package/src/modules/plugins/components/plugin-detail/permissions/filesystem-permissions.tsx +0 -68
  123. package/src/modules/plugins/components/plugin-detail/permissions/index.ts +0 -6
  124. package/src/modules/plugins/components/plugin-detail/permissions/network-permissions.tsx +0 -43
  125. package/src/modules/plugins/components/plugin-detail/permissions/platform-services.tsx +0 -242
  126. package/src/modules/plugins/components/plugin-detail/permissions/resource-quotas.tsx +0 -96
  127. package/src/modules/plugins/components/plugin-detail/permissions/shell-permissions.tsx +0 -55
  128. package/src/modules/plugins/components/plugin-detail/permissions-view.tsx +0 -47
  129. package/src/modules/plugins/components/plugin-detail/plugin-header.tsx +0 -169
  130. package/src/modules/plugins/components/plugin-detail/rest-routes-table.tsx +0 -159
  131. package/src/modules/plugins/components/plugin-detail/workflows-table.tsx +0 -40
  132. package/src/modules/plugins/components/plugin-grid.tsx +0 -20
  133. package/src/modules/plugins/components/plugin-table.tsx +0 -178
  134. package/src/modules/plugins/pages/marketplace-page.tsx +0 -200
  135. package/src/modules/plugins/pages/plugin-detail-page.tsx +0 -1145
  136. package/src/modules/plugins/routes/index.tsx +0 -48
  137. package/src/modules/plugins/utils/index.ts +0 -1
  138. package/src/modules/plugins/utils/schema-helpers.ts +0 -21
  139. package/src/modules/settings/components/api-routes-viewer.tsx +0 -415
  140. package/src/modules/settings/components/appearance-settings.tsx +0 -200
  141. package/src/modules/settings/components/configuration-settings.tsx +0 -321
  142. package/src/modules/settings/components/data-privacy-settings.tsx +0 -111
  143. package/src/modules/settings/components/experimental-settings.tsx +0 -243
  144. package/src/modules/settings/components/navigation-settings.tsx +0 -198
  145. package/src/modules/settings/components/notifications-settings.tsx +0 -40
  146. package/src/modules/settings/pages/settings-page.tsx +0 -298
  147. package/src/modules/settings/routes/index.tsx +0 -47
  148. package/src/pages/README-assistant.md +0 -91
  149. package/src/pages/login-page.tsx +0 -177
  150. package/src/pages/not-found-page.tsx +0 -85
  151. package/src/providers/auth-provider.tsx +0 -40
  152. package/src/providers/command-palette-provider.tsx +0 -193
  153. package/src/providers/data-sources-provider.tsx +0 -27
  154. package/src/providers/devtools-provider.tsx +0 -72
  155. package/src/providers/navigation-items-provider.tsx +0 -38
  156. package/src/providers/registry-v2-provider.tsx +0 -93
  157. package/src/providers/settings-provider.tsx +0 -158
  158. package/src/router.tsx +0 -302
  159. package/src/routes/helpers.tsx +0 -25
  160. package/src/routes/plugin-page-v2.tsx +0 -52
  161. package/src/routes/types.ts +0 -18
  162. package/src/styles/antd-overrides.css +0 -211
  163. package/src/styles/base.css +0 -190
  164. package/src/styles/settings.css +0 -75
  165. package/src/styles/variables.css +0 -94
  166. package/src/utils/analytics.ts +0 -183
  167. package/src/utils/apply-navigation-categories.ts +0 -83
  168. package/src/utils/commands.ts +0 -252
  169. package/src/utils/export.ts +0 -174
  170. package/src/utils/format-date.ts +0 -166
  171. package/src/utils/logger.ts +0 -110
  172. package/tailwind.config.ts +0 -13
  173. package/tsconfig.json +0 -13
  174. package/vitest-setup.ts +0 -1
  175. /package/{public → dist}/favicon.svg +0 -0
@@ -1,25 +0,0 @@
1
- import { useState, useEffect } from 'react';
2
- import { devToolsStore } from '@kb-labs/studio-devtools';
3
- import type { DevToolsChannel } from '@kb-labs/studio-devtools';
4
-
5
- export interface UseDevToolsStoreReturn {
6
- channels: readonly DevToolsChannel[];
7
- clear(): void;
8
- }
9
-
10
- /**
11
- * Subscribe to the DevTools store and re-render on any change.
12
- * Uses the same forceUpdate pattern as ReactQueryDevtools.
13
- */
14
- export function useDevToolsStore(): UseDevToolsStoreReturn {
15
- const [, forceUpdate] = useState(0);
16
-
17
- useEffect(() => {
18
- return devToolsStore.subscribe(() => { forceUpdate((n) => n + 1); });
19
- }, []);
20
-
21
- return {
22
- channels: devToolsStore.getChannels(),
23
- clear: () => { devToolsStore.clear(); },
24
- };
25
- }
@@ -1,101 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/hooks/use-feature-flags
3
- * Hook to access and toggle feature flags
4
- */
5
-
6
- import { useCallback, useMemo } from 'react';
7
- import { useSettings } from '@/providers/settings-provider';
8
- import type { FeatureId } from '@/config/feature-flags';
9
- import { isFeatureEnabled as isEnabled, areDependenciesMet } from '@/config/feature-flags';
10
-
11
- export interface UseFeatureFlagsReturn {
12
- /** Check if a feature is enabled */
13
- isEnabled: (featureId: FeatureId) => boolean;
14
- /** Toggle a feature on/off */
15
- toggleFeature: (featureId: FeatureId) => void;
16
- /** Enable a feature */
17
- enableFeature: (featureId: FeatureId) => void;
18
- /** Disable a feature */
19
- disableFeature: (featureId: FeatureId) => void;
20
- /** Get all enabled feature IDs */
21
- enabledFeatures: FeatureId[];
22
- /** Check if feature dependencies are met */
23
- areDependenciesMet: (featureId: FeatureId) => boolean;
24
- }
25
-
26
- export function useFeatureFlags(): UseFeatureFlagsReturn {
27
- const { settings, updateSettings } = useSettings();
28
- const enabledFeatures = useMemo(() => settings.experimental?.enabledFeatures ?? [], [settings.experimental?.enabledFeatures]);
29
-
30
- // Create a preferences map for efficient lookup
31
- const preferences = useMemo(() => {
32
- const map: Record<FeatureId, boolean> = {} as Record<FeatureId, boolean>;
33
- enabledFeatures.forEach((id) => {
34
- map[id] = true;
35
- });
36
- return map;
37
- }, [enabledFeatures]);
38
-
39
- const isFeatureEnabled = useCallback(
40
- (featureId: FeatureId): boolean => {
41
- return isEnabled(featureId, preferences);
42
- },
43
- [preferences]
44
- );
45
-
46
- const toggleFeature = useCallback(
47
- (featureId: FeatureId) => {
48
- const currentlyEnabled = enabledFeatures.includes(featureId);
49
- const newFeatures = currentlyEnabled
50
- ? enabledFeatures.filter((id) => id !== featureId)
51
- : [...enabledFeatures, featureId];
52
-
53
- updateSettings({
54
- experimental: {
55
- enabledFeatures: newFeatures,
56
- },
57
- });
58
- },
59
- [enabledFeatures, updateSettings]
60
- );
61
-
62
- const enableFeature = useCallback(
63
- (featureId: FeatureId) => {
64
- if (!enabledFeatures.includes(featureId)) {
65
- updateSettings({
66
- experimental: {
67
- enabledFeatures: [...enabledFeatures, featureId],
68
- },
69
- });
70
- }
71
- },
72
- [enabledFeatures, updateSettings]
73
- );
74
-
75
- const disableFeature = useCallback(
76
- (featureId: FeatureId) => {
77
- updateSettings({
78
- experimental: {
79
- enabledFeatures: enabledFeatures.filter((id) => id !== featureId),
80
- },
81
- });
82
- },
83
- [enabledFeatures, updateSettings]
84
- );
85
-
86
- const checkDependencies = useCallback(
87
- (featureId: FeatureId): boolean => {
88
- return areDependenciesMet(featureId, preferences);
89
- },
90
- [preferences]
91
- );
92
-
93
- return {
94
- isEnabled: isFeatureEnabled,
95
- toggleFeature,
96
- enableFeature,
97
- disableFeature,
98
- enabledFeatures,
99
- areDependenciesMet: checkDependencies,
100
- };
101
- }
package/src/index.css DELETED
@@ -1,10 +0,0 @@
1
- /* Theme variables and base styles - must be first */
2
- @import './styles/variables.css';
3
- @import './styles/base.css';
4
- @import './styles/antd-overrides.css';
5
- @import './styles/settings.css';
6
-
7
- @tailwind base;
8
- @tailwind components;
9
- @tailwind utilities;
10
-
@@ -1,122 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/layouts/DashboardGrid
3
- * Dashboard Grid layout - responsive CSS Grid using design tokens
4
- *
5
- * Refactored to use spacing tokens and remove inline styles where possible.
6
- */
7
-
8
- import * as React from 'react';
9
- import { spacing } from '@kb-labs/studio-ui-core';
10
- import { useUITheme } from '@kb-labs/studio-ui-kit';
11
-
12
- export interface DashboardGridProps {
13
- children: React.ReactNode;
14
- cols?: {
15
- sm: number;
16
- md: number;
17
- lg: number;
18
- };
19
- rowHeight?: number;
20
- gap?: number;
21
- }
22
-
23
- export function DashboardGrid({
24
- children,
25
- cols = { sm: 4, md: 8, lg: 12 },
26
- rowHeight = 8,
27
- gap = 16
28
- }: DashboardGridProps) {
29
- const { token } = useUITheme();
30
- const childrenArray = React.Children.toArray(children);
31
-
32
- // Use spacing tokens for gap if available
33
- const gridGap = gap === 16 ? spacing[4] : gap === 8 ? spacing[2] : `${gap}px`;
34
-
35
- return (
36
- <div
37
- className="widget-dashboard-grid"
38
- style={
39
- {
40
- '--cols-sm': cols.sm,
41
- '--cols-md': cols.md,
42
- '--cols-lg': cols.lg,
43
- '--row-height': `${rowHeight * 8}px`,
44
- '--gap': gridGap,
45
- '--border-color': token.colorBorder,
46
- } as React.CSSProperties
47
- }
48
- >
49
- {childrenArray.map((child, index) => {
50
- // Extract layoutHint from child props if available
51
- const layoutHint = (child as React.ReactElement)?.props?.layoutHint || { w: 4, h: 4 };
52
- const { w, h, minW, minH, height } = layoutHint;
53
-
54
- // Calculate height based on layoutHint.height
55
- let itemHeight: string | undefined;
56
- let itemMaxHeight: string | undefined;
57
- let itemMinHeight: string | undefined;
58
-
59
- if (height === 'fit-content') {
60
- itemHeight = 'fit-content';
61
- } else if (typeof height === 'number') {
62
- itemHeight = `${height}px`;
63
- } else if (height === 'auto' || height === undefined) {
64
- // Auto height: use grid rows but allow content to expand
65
- itemMinHeight = minH ? `${minH * rowHeight * 8}px` : `${h * rowHeight * 8}px`;
66
- } else {
67
- // Fallback: use grid-based height calculation
68
- itemMinHeight = minH ? `${minH * rowHeight * 8}px` : `${h * rowHeight * 8}px`;
69
- }
70
-
71
- return (
72
- <div
73
- key={index}
74
- className="widget-dashboard-grid__item"
75
- style={
76
- {
77
- gridColumn: `span ${w}`,
78
- gridRow: height === 'fit-content' ? 'span 1' : `span ${h}`,
79
- minWidth: minW ? `${minW * (100 / cols.lg)}%` : undefined,
80
- minHeight: itemMinHeight,
81
- height: itemHeight,
82
- maxHeight: itemMaxHeight,
83
- } as React.CSSProperties
84
- }
85
- >
86
- {child}
87
- </div>
88
- );
89
- })}
90
- <style>{`
91
- .widget-dashboard-grid {
92
- display: grid;
93
- grid-template-columns: repeat(var(--cols-sm), 1fr);
94
- gap: var(--gap);
95
- grid-auto-rows: minmax(var(--row-height), auto);
96
- align-items: start;
97
- }
98
- @media (min-width: 768px) {
99
- .widget-dashboard-grid {
100
- grid-template-columns: repeat(var(--cols-md), 1fr);
101
- }
102
- }
103
- @media (min-width: 1024px) {
104
- .widget-dashboard-grid {
105
- grid-template-columns: repeat(var(--cols-lg), 1fr);
106
- }
107
- }
108
- .widget-dashboard-grid__item {
109
- min-height: var(--row-height);
110
- display: flex;
111
- flex-direction: column;
112
- }
113
- .widget-dashboard-grid__item > * {
114
- flex: 1;
115
- min-height: 0;
116
- }
117
- `}</style>
118
- </div>
119
- );
120
- }
121
-
122
-
@@ -1,12 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/layouts
3
- * Layout components
4
- */
5
-
6
- export { DashboardGrid } from './dashboard-grid';
7
- export type { DashboardGridProps } from './dashboard-grid';
8
-
9
- export { TwoPane } from './two-pane';
10
- export type { TwoPaneProps } from './two-pane';
11
-
12
-
@@ -1,134 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/layouts/TwoPane
3
- * Two Pane layout - flex-based with optional resizer using design tokens
4
- *
5
- * Refactored to use Ant Design theme tokens for colors and transitions.
6
- */
7
-
8
- import * as React from 'react';
9
- import { useUITheme } from '@kb-labs/studio-ui-kit';
10
-
11
- export interface TwoPaneProps {
12
- left: React.ReactNode;
13
- right: React.ReactNode;
14
- leftWidth?: string;
15
- resizable?: boolean;
16
- minLeftWidth?: string;
17
- maxLeftWidth?: string;
18
- }
19
-
20
- export function TwoPane({
21
- left,
22
- right,
23
- leftWidth = '50%',
24
- resizable = false,
25
- minLeftWidth = '20%',
26
- maxLeftWidth = '80%',
27
- }: TwoPaneProps) {
28
- const { token } = useUITheme();
29
- const [leftWidthState, setLeftWidthState] = React.useState(leftWidth);
30
- const [isResizing, setIsResizing] = React.useState(false);
31
- const containerRef = React.useRef<HTMLDivElement>(null);
32
-
33
- const handleMouseDown = () => {
34
- if (!resizable) {return;}
35
- setIsResizing(true);
36
- };
37
-
38
- const handleMouseMove = React.useCallback(
39
- (e: MouseEvent) => {
40
- if (!isResizing || !containerRef.current) {return;}
41
-
42
- const container = containerRef.current;
43
- const rect = container.getBoundingClientRect();
44
- const newLeftWidth = ((e.clientX - rect.left) / rect.width) * 100;
45
-
46
- // Apply min/max constraints
47
- const min = parseFloat(minLeftWidth);
48
- const max = parseFloat(maxLeftWidth);
49
- const clamped = Math.max(min, Math.min(max, newLeftWidth));
50
-
51
- setLeftWidthState(`${clamped}%`);
52
- },
53
- [isResizing, minLeftWidth, maxLeftWidth]
54
- );
55
-
56
- const handleMouseUp = () => {
57
- setIsResizing(false);
58
- };
59
-
60
- React.useEffect(() => {
61
- if (isResizing) {
62
- document.addEventListener('mousemove', handleMouseMove);
63
- document.addEventListener('mouseup', handleMouseUp);
64
- return () => {
65
- document.removeEventListener('mousemove', handleMouseMove);
66
- document.removeEventListener('mouseup', handleMouseUp);
67
- };
68
- }
69
- }, [isResizing, handleMouseMove]);
70
-
71
- return (
72
- <div
73
- className="widget-two-pane"
74
- ref={containerRef}
75
- style={
76
- {
77
- '--border-color': token.colorBorder,
78
- '--link-color': token.colorLink,
79
- '--transition-duration': `${token.motionDurationMid}`,
80
- } as React.CSSProperties
81
- }
82
- >
83
- <div
84
- className="widget-two-pane__left"
85
- style={
86
- {
87
- width: leftWidthState,
88
- minWidth: minLeftWidth,
89
- maxWidth: maxLeftWidth,
90
- } as React.CSSProperties
91
- }
92
- >
93
- {left}
94
- </div>
95
- {resizable && (
96
- <div
97
- className="widget-two-pane__resizer"
98
- onMouseDown={handleMouseDown}
99
- data-resizing={isResizing}
100
- />
101
- )}
102
- <div className="widget-two-pane__right">{right}</div>
103
- <style>{`
104
- .widget-two-pane {
105
- display: flex;
106
- height: 100%;
107
- width: 100%;
108
- }
109
- .widget-two-pane__left {
110
- flex-shrink: 0;
111
- overflow: auto;
112
- border-right: 1px solid var(--border-color);
113
- }
114
- .widget-two-pane__resizer {
115
- width: 4px;
116
- background: var(--border-color);
117
- cursor: col-resize;
118
- flex-shrink: 0;
119
- transition: background var(--transition-duration);
120
- }
121
- .widget-two-pane__resizer:hover,
122
- .widget-two-pane__resizer[data-resizing="true"] {
123
- background: var(--link-color);
124
- }
125
- .widget-two-pane__right {
126
- flex: 1;
127
- overflow: auto;
128
- }
129
- `}</style>
130
- </div>
131
- );
132
- }
133
-
134
-
package/src/main.tsx DELETED
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom/client';
3
- import { App } from './App';
4
- import '@kb-labs/studio-ui-kit/dist/index.css';
5
- import { registerIconRenderer } from '@kb-labs/studio-ui-kit';
6
- import { renderIcon } from './components/ui/icons';
7
- import './index.css';
8
-
9
- registerIconRenderer(renderIcon);
10
-
11
- ReactDOM.createRoot(document.getElementById('root')!).render(
12
- <React.StrictMode>
13
- <App />
14
- </React.StrictMode>
15
- );
@@ -1,257 +0,0 @@
1
- import { useMemo } from 'react';
2
- import { UIText, UICard, UIAreaChart, useChartColors } from '@kb-labs/studio-ui-kit';
3
- import type { DailyStats } from '@kb-labs/studio-data-client';
4
- import dayjs from 'dayjs';
5
-
6
- /**
7
- * Configuration for chart metrics
8
- */
9
- export interface ChartMetricConfig {
10
- /**
11
- * Metric key from DailyStats.metrics
12
- */
13
- key: string;
14
-
15
- /**
16
- * Display label for the metric
17
- */
18
- label: string;
19
-
20
- /**
21
- * Optional transformer function to convert raw value to display value
22
- * Example: (v) => v / 1000 to convert tokens to K tokens
23
- */
24
- transform?: (value: number) => number;
25
-
26
- /**
27
- * Optional formatter for tooltip
28
- */
29
- format?: (value: number) => string;
30
- }
31
-
32
- export interface AnalyticsDailyStatsChartProps {
33
- /**
34
- * Daily statistics data
35
- */
36
- data: DailyStats[] | undefined;
37
-
38
- /**
39
- * Loading state
40
- */
41
- loading?: boolean;
42
-
43
- /**
44
- * Chart title
45
- */
46
- title: string;
47
-
48
- /**
49
- * Metrics to display on the chart
50
- * Each metric will be shown as a separate line
51
- */
52
- metrics: ChartMetricConfig[];
53
-
54
- /**
55
- * Optional card style
56
- */
57
- style?: React.CSSProperties;
58
-
59
- /**
60
- * Chart height in pixels
61
- */
62
- height?: number;
63
- }
64
-
65
- /**
66
- * Reusable daily statistics chart component
67
- *
68
- * Displays time-series chart with multiple metrics for analytics pages.
69
- * Used across LLM, Embeddings, VectorStore, Cache, and Storage analytics.
70
- *
71
- * @example
72
- * ```tsx
73
- * <AnalyticsDailyStatsChart
74
- * data={dailyStats}
75
- * loading={isLoading}
76
- * title="Daily LLM Usage Trend"
77
- * metrics={[
78
- * { key: 'count', label: 'Requests' },
79
- * { key: 'totalTokens', label: 'Tokens (K)', transform: (v) => v / 1000 },
80
- * { key: 'totalCost', label: 'Cost ($)', format: (v) => `$${v.toFixed(2)}` },
81
- * ]}
82
- * />
83
- * ```
84
- */
85
- export function AnalyticsDailyStatsChart({
86
- data,
87
- loading = false,
88
- title,
89
- metrics,
90
- style,
91
- height = 350,
92
- }: AnalyticsDailyStatsChartProps) {
93
- const palette = useChartColors();
94
-
95
- // Memoize chart colors to ensure stability across renders
96
- const chartColors = useMemo(() => {
97
- console.log('[useMemo] Input:', {
98
- paletteColors: palette.colors,
99
- isArray: Array.isArray(palette.colors),
100
- length: palette.colors?.length,
101
- first3: palette.colors.slice(0, 3),
102
- metricsLength: metrics.length,
103
- });
104
-
105
- const result = palette.colors.slice(0, metrics.length);
106
-
107
- console.log('[useMemo] Output:', {
108
- result,
109
- isArray: Array.isArray(result),
110
- length: result.length,
111
- });
112
-
113
- return result;
114
- }, [palette.colors, metrics.length]);
115
-
116
- console.log('[AnalyticsDailyStatsChart] Colors:', {
117
- metricsCount: metrics.length,
118
- chartColors,
119
- paletteColors: palette.colors,
120
- });
121
-
122
- // Transform data for chart
123
- const chartData =
124
- data?.flatMap((stat) => {
125
- const rows: Array<{ date: string; category: string; value: number }> = [];
126
-
127
- for (const metric of metrics) {
128
- let value: number;
129
-
130
- if (metric.key === 'count') {
131
- // Special case: count is top-level field
132
- value = stat.count;
133
- } else {
134
- // Extract from metrics object
135
- value = stat.metrics?.[metric.key] ?? 0;
136
- }
137
-
138
- // Apply transformation if provided
139
- if (metric.transform) {
140
- value = metric.transform(value);
141
- }
142
-
143
- rows.push({
144
- date: dayjs(stat.date).format('YYYY-MM-DD'), // Ensure consistent date format
145
- category: metric.label,
146
- value,
147
- });
148
- }
149
-
150
- return rows;
151
- }) ?? [];
152
-
153
- console.log('[AnalyticsDailyStatsChart] Chart data:', {
154
- dataLength: chartData.length,
155
- uniqueCategories: [...new Set(chartData.map(d => d.category))],
156
- sampleData: chartData.slice(0, 3),
157
- });
158
-
159
-
160
- const cardStyle = { marginTop: 16, ...style } as any;
161
- return (
162
- <UICard title={title} style={cardStyle}>
163
- {loading && (
164
- <div style={{ textAlign: 'center', padding: '40px 0' }}>
165
- <UIText color="secondary">Loading chart data...</UIText>
166
- </div>
167
- )}
168
-
169
- {!loading && chartData.length > 0 && (
170
- <div>
171
- {/* Custom Legend */}
172
- <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 12, gap: 16 }}>
173
- {metrics.map((metric, index) => (
174
- <div key={metric.label} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
175
- <span
176
- style={{
177
- display: 'inline-block',
178
- width: 10,
179
- height: 10,
180
- borderRadius: '50%',
181
- backgroundColor: chartColors[index % chartColors.length],
182
- }}
183
- />
184
- <span style={{ fontSize: 13, fontWeight: 500 }}>{metric.label}</span>
185
- </div>
186
- ))}
187
- </div>
188
-
189
- <UIAreaChart
190
- data={chartData}
191
- xField="date"
192
- yField="value"
193
- colorField="category"
194
- colors={chartColors}
195
- height={height}
196
- axis={{
197
- x: {
198
- label: {
199
- autoRotate: false,
200
- },
201
- },
202
- y: {
203
- label: {
204
- formatter: (v: string) => {
205
- const num = Number(v);
206
- if (num >= 1000000) {return `${(num / 1000000).toFixed(1)}M`;}
207
- if (num >= 1000) {return `${(num / 1000).toFixed(1)}K`;}
208
- return num.toLocaleString();
209
- },
210
- },
211
- },
212
- }}
213
- style={{
214
- fillOpacity: 0.3,
215
- }}
216
- legend={false}
217
- tooltip={{
218
- title: (d: any) => d.date,
219
- items: [
220
- (d: any) => {
221
- const metric = metrics.find((m) => m.label === d.category);
222
- const metricIndex = metrics.findIndex((m) => m.label === d.category);
223
- let formattedValue = d.value?.toLocaleString() || '0';
224
-
225
- if (metric?.format && d.value != null) {
226
- formattedValue = metric.format(d.value);
227
- }
228
-
229
- const tooltipColor = chartColors[metricIndex >= 0 ? metricIndex : 0];
230
-
231
- console.log('[Tooltip] Color:', {
232
- category: d.category,
233
- metricIndex,
234
- tooltipColor,
235
- chartColors,
236
- });
237
-
238
- return {
239
- name: d.category,
240
- value: formattedValue,
241
- color: tooltipColor,
242
- };
243
- },
244
- ],
245
- }}
246
- />
247
- </div>
248
- )}
249
-
250
- {!loading && chartData.length === 0 && (
251
- <div style={{ textAlign: 'center', padding: '40px 0' }}>
252
- <UIText color="secondary">No data available for the selected date range</UIText>
253
- </div>
254
- )}
255
- </UICard>
256
- );
257
- }