@kb-labs/studio-app 0.6.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,177 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/pages/login-page
3
- * Login page placeholder - mock authentication
4
- */
5
-
6
- import * as React from 'react';
7
- import { useNavigate } from 'react-router-dom';
8
- import {
9
- UICard, UIButton, UISpace, UITitle, UITypographyText, UITypographyParagraph,
10
- UISelect, UIDivider, UIMessage, UIIcon,
11
- } from '@kb-labs/studio-ui-kit';
12
- import { useAuth, type UserRole } from '@/providers/auth-provider';
13
-
14
- export function LoginPage() {
15
- const navigate = useNavigate();
16
- const { setRole } = useAuth();
17
- const [selectedRole, setSelectedRole] = React.useState<UserRole>('operator');
18
-
19
- const handleLogin = () => {
20
- setRole(selectedRole);
21
- navigate('/');
22
- };
23
-
24
- const handleSSOLogin = () => {
25
- UIMessage.info('SSO аутентификация будет реализована позже');
26
- // TODO: Implement SSO authentication
27
- };
28
-
29
- return (
30
- <div
31
- style={{
32
- display: 'flex',
33
- alignItems: 'center',
34
- justifyContent: 'center',
35
- minHeight: '100vh',
36
- backgroundColor: 'var(--bg-tertiary)',
37
- padding: '2rem',
38
- }}
39
- >
40
- <UICard
41
- style={{
42
- maxWidth: '480px',
43
- width: '100%',
44
- borderRadius: '16px',
45
- boxShadow: '0 20px 60px rgba(0,0,0,0.3)',
46
- }}
47
- styles={{ body: { padding: '3rem' } }}
48
- >
49
- <UISpace direction="vertical" size="large" style={{ width: '100%', textAlign: 'center' }}>
50
- {/* Logo */}
51
- <div
52
- style={{
53
- width: '80px',
54
- height: '80px',
55
- margin: '0 auto',
56
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
57
- borderRadius: '20px',
58
- display: 'flex',
59
- alignItems: 'center',
60
- justifyContent: 'center',
61
- fontSize: '40px',
62
- }}
63
- >
64
- <UIIcon name="RocketOutlined" style={{ color: 'white' }} />
65
- </div>
66
-
67
- {/* Title */}
68
- <div>
69
- <UITitle level={2} style={{ marginBottom: 8 }}>
70
- KB Labs Studio
71
- </UITitle>
72
- <UITypographyText type="secondary">Добро пожаловать в платформу</UITypographyText>
73
- </div>
74
-
75
- <UIDivider style={{ margin: '8px 0' }} />
76
-
77
- {/* Mock Auth Notice */}
78
- <div
79
- style={{
80
- padding: '16px',
81
- backgroundColor: 'var(--bg-tertiary)',
82
- borderRadius: '8px',
83
- border: '1px solid var(--border-primary)',
84
- }}
85
- >
86
- <UISpace direction="vertical" size="small" style={{ width: '100%' }}>
87
- <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
88
- <UIIcon name="LockOutlined" style={{ color: '#667eea' }} />
89
- <UITypographyText strong style={{ color: '#667eea' }}>
90
- Режим разработки
91
- </UITypographyText>
92
- </div>
93
- <UITypographyParagraph
94
- type="secondary"
95
- style={{ margin: 0, fontSize: '0.875rem', textAlign: 'left' }}
96
- >
97
- Это заглушка для входа. Выберите роль и войдите без пароля.
98
- </UITypographyParagraph>
99
- </UISpace>
100
- </div>
101
-
102
- {/* Role Selector */}
103
- <div style={{ width: '100%', textAlign: 'left' }}>
104
- <UITypographyText strong style={{ display: 'block', marginBottom: 8 }}>
105
- Выберите роль:
106
- </UITypographyText>
107
- <UISelect
108
- value={selectedRole}
109
- onChange={(v) => setSelectedRole(v as UserRole)}
110
- style={{ width: '100%' }}
111
- size="large"
112
- options={[
113
- {
114
- label: 'Viewer — Просмотр данных',
115
- value: 'viewer',
116
- },
117
- {
118
- label: 'Operator — Управление системой',
119
- value: 'operator',
120
- },
121
- {
122
- label: 'Admin — Полный доступ',
123
- value: 'admin',
124
- },
125
- ]}
126
- />
127
- </div>
128
-
129
- {/* Login Buttons */}
130
- <UISpace direction="vertical" size="middle" style={{ width: '100%' }}>
131
- <UIButton
132
- variant="primary"
133
- size="large"
134
- block
135
- icon={<UIIcon name="RocketOutlined" />}
136
- onClick={handleLogin}
137
- style={{
138
- height: '48px',
139
- fontSize: '16px',
140
- fontWeight: 500,
141
- }}
142
- >
143
- Войти в систему
144
- </UIButton>
145
-
146
- <UIDivider style={{ margin: '8px 0' }}>
147
- <UITypographyText type="secondary" style={{ fontSize: '0.75rem' }}>
148
- или
149
- </UITypographyText>
150
- </UIDivider>
151
-
152
- <UIButton
153
- size="large"
154
- block
155
- icon={<UIIcon name="SafetyOutlined" />}
156
- onClick={handleSSOLogin}
157
- style={{
158
- height: '48px',
159
- fontSize: '16px',
160
- fontWeight: 500,
161
- }}
162
- >
163
- Войти через SSO
164
- </UIButton>
165
- </UISpace>
166
-
167
- {/* Footer */}
168
- <div style={{ marginTop: '16px' }}>
169
- <UITypographyText type="secondary" style={{ fontSize: '0.75rem' }}>
170
- © 2025 KB Labs Studio. Development Preview.
171
- </UITypographyText>
172
- </div>
173
- </UISpace>
174
- </UICard>
175
- </div>
176
- );
177
- }
@@ -1,85 +0,0 @@
1
- import { useNavigate, useLocation } from 'react-router-dom';
2
- import { UIButton } from '@kb-labs/studio-ui-kit';
3
- import { ArrowLeft, Home } from 'lucide-react';
4
-
5
- export function NotFoundPage() {
6
- const navigate = useNavigate();
7
- const location = useLocation();
8
-
9
- return (
10
- <div style={{
11
- display: 'flex',
12
- alignItems: 'center',
13
- justifyContent: 'center',
14
- minHeight: '100vh',
15
- backgroundColor: 'var(--bg-primary)',
16
- padding: 24,
17
- }}>
18
- <div style={{ textAlign: 'center', maxWidth: 400 }}>
19
- <div style={{
20
- fontSize: 96,
21
- fontWeight: 700,
22
- lineHeight: 1,
23
- letterSpacing: '-4px',
24
- color: 'var(--border-secondary)',
25
- fontFamily: 'var(--font-heading)',
26
- marginBottom: 24,
27
- userSelect: 'none',
28
- }}>
29
- 404
30
- </div>
31
-
32
- <div style={{
33
- fontSize: 18,
34
- fontWeight: 600,
35
- color: 'var(--text-primary)',
36
- marginBottom: 8,
37
- }}>
38
- Page not found
39
- </div>
40
-
41
- <div style={{
42
- fontSize: 13,
43
- color: 'var(--text-secondary)',
44
- marginBottom: 4,
45
- lineHeight: 1.5,
46
- }}>
47
- The page you're looking for doesn't exist or has been moved.
48
- </div>
49
-
50
- {location.pathname !== '/' && (
51
- <div style={{
52
- fontSize: 11,
53
- color: 'var(--text-tertiary)',
54
- marginBottom: 32,
55
- fontFamily: 'var(--font-mono, monospace)',
56
- background: 'var(--bg-tertiary)',
57
- border: '1px solid var(--border-primary)',
58
- borderRadius: 6,
59
- padding: '4px 10px',
60
- display: 'inline-block',
61
- marginTop: 12,
62
- }}>
63
- {location.pathname}
64
- </div>
65
- )}
66
-
67
- <div style={{ display: 'flex', gap: 8, justifyContent: 'center', marginTop: 24 }}>
68
- <UIButton
69
- variant="primary"
70
- icon={<Home size={14} />}
71
- onClick={() => navigate('/')}
72
- >
73
- Go home
74
- </UIButton>
75
- <UIButton
76
- icon={<ArrowLeft size={14} />}
77
- onClick={() => navigate(-1)}
78
- >
79
- Go back
80
- </UIButton>
81
- </div>
82
- </div>
83
- </div>
84
- );
85
- }
@@ -1,40 +0,0 @@
1
- import { createContext, useContext, useState, useEffect, type ReactNode } from 'react';
2
-
3
- export type UserRole = 'viewer' | 'operator' | 'admin';
4
-
5
- interface AuthState {
6
- role: UserRole;
7
- setRole: (role: UserRole) => void;
8
- }
9
-
10
- const AuthContext = createContext<AuthState | null>(null);
11
-
12
- export function AuthProvider({ children }: { children: ReactNode }) {
13
- const [role, setRoleState] = useState<UserRole>(
14
- () => (localStorage.getItem('studio-user-role') as UserRole) || 'operator'
15
- );
16
-
17
- useEffect(() => {
18
- localStorage.setItem('studio-user-role', role);
19
- }, [role]);
20
-
21
- const setRole = (newRole: UserRole) => {
22
- setRoleState(newRole);
23
- };
24
-
25
- return <AuthContext.Provider value={{ role, setRole }}>{children}</AuthContext.Provider>;
26
- }
27
-
28
- export function useAuth() {
29
- const context = useContext(AuthContext);
30
- if (!context) {
31
- throw new Error('useAuth must be used within AuthProvider');
32
- }
33
- return context;
34
- }
35
-
36
- export function useRole() {
37
- const { role } = useAuth();
38
- return role;
39
- }
40
-
@@ -1,193 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/providers/command-palette-provider
3
- * Command Palette provider - manages commands and quick search
4
- */
5
-
6
- import * as React from 'react';
7
- import { useNavigate } from 'react-router-dom';
8
- import { UIMessage } from '@kb-labs/studio-ui-kit';
9
- import { useQueryClient } from '@tanstack/react-query';
10
- import { useDataSources } from './data-sources-provider';
11
- import { useSettings } from './settings-provider';
12
- import { getCommands, saveRecentCommand, getRecentCommands } from '@/utils/commands';
13
- import { KBQuickSearch, type SearchableItem } from '@/components/ui';
14
-
15
- interface CommandPaletteContextValue {
16
- /** Open command palette */
17
- open: () => void;
18
- /** Close command palette */
19
- close: () => void;
20
- /** Toggle command palette */
21
- toggle: () => void;
22
- /** Check if palette is open */
23
- isOpen: boolean;
24
- }
25
-
26
- const CommandPaletteContext = React.createContext<CommandPaletteContextValue | undefined>(
27
- undefined
28
- );
29
-
30
- export function CommandPaletteProvider({ children }: { children: React.ReactNode }) {
31
- const [isOpen, setIsOpen] = React.useState(false);
32
- const navigate = useNavigate();
33
- const { settings, updateSettings } = useSettings();
34
- const queryClient = useQueryClient();
35
- const refresh = React.useCallback(
36
- () => queryClient.invalidateQueries({ queryKey: ['studio-registry-v2'] }),
37
- [queryClient],
38
- );
39
- const sources = useDataSources();
40
-
41
- // Commands configuration
42
- const allCommands = React.useMemo(
43
- () =>
44
- getCommands({
45
- navigate,
46
- toggleTheme: () => {
47
- const currentTheme = settings.appearance.theme;
48
- const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
49
- updateSettings({ appearance: { ...settings.appearance, theme: newTheme } });
50
- UIMessage.success(`Switched to ${newTheme} mode`);
51
- },
52
- refreshRegistry: async () => {
53
- try {
54
- await refresh();
55
- UIMessage.success('Registry refreshed successfully');
56
- } catch (error) {
57
- UIMessage.error(
58
- `Failed to refresh registry: ${error instanceof Error ? error.message : String(error)}`
59
- );
60
- }
61
- },
62
- invalidateCache: async () => {
63
- try {
64
- const result = await sources.cache.invalidateCache();
65
- UIMessage.success(
66
- `Cache invalidated! Rev: ${result.previousRev ?? 'N/A'} → ${result.newRev}`
67
- );
68
- await refresh();
69
- } catch (error) {
70
- UIMessage.error(
71
- `Failed to invalidate cache: ${error instanceof Error ? error.message : String(error)}`
72
- );
73
- }
74
- },
75
- openQuickSearch: () => {
76
- setIsOpen(true);
77
- },
78
- }),
79
- [navigate, settings, updateSettings, refresh, sources]
80
- );
81
-
82
- // Get recent commands and merge with all commands
83
- const items = React.useMemo(() => {
84
- const recentIds = getRecentCommands();
85
- const recentCommands: SearchableItem[] = [];
86
- const otherCommands: SearchableItem[] = [];
87
-
88
- allCommands.forEach((cmd) => {
89
- const item: SearchableItem = {
90
- id: cmd.id,
91
- title: cmd.title,
92
- description: cmd.description,
93
- category: cmd.category as SearchableItem['category'],
94
- path: cmd.path,
95
- icon: undefined, // Explicitly set to undefined - icons will be rendered based on category
96
- badge: cmd.shortcut,
97
- };
98
-
99
- if (recentIds.includes(cmd.id)) {
100
- recentCommands.push(item);
101
- } else {
102
- otherCommands.push(item);
103
- }
104
- });
105
-
106
- // Sort recent by recency, others by priority
107
- const sortedRecent = recentCommands.sort(
108
- (a, b) => recentIds.indexOf(a.id) - recentIds.indexOf(b.id)
109
- );
110
-
111
- const sortedOthers = otherCommands.sort((a, b) => {
112
- const cmdA = allCommands.find((c) => c.id === a.id);
113
- const cmdB = allCommands.find((c) => c.id === b.id);
114
- return (cmdB?.priority ?? 0) - (cmdA?.priority ?? 0);
115
- });
116
-
117
- return [...sortedRecent, ...sortedOthers];
118
- }, [allCommands]);
119
-
120
- // Handle command execution
121
- const handleNavigate = React.useCallback(
122
- (path: string) => {
123
- const command = allCommands.find((cmd) => cmd.path === path);
124
- if (!command) {return;}
125
-
126
- // Save to recent
127
- saveRecentCommand(command.id);
128
-
129
- // Execute action or navigate
130
- if (command.action) {
131
- command.action();
132
- } else if (command.path) {
133
- // Handle URL params (e.g., /settings?tab=appearance)
134
- if (command.path.includes('?')) {
135
- const [basePath, search] = command.path.split('?');
136
- navigate({ pathname: basePath, search: `?${search}` });
137
- } else {
138
- navigate(command.path);
139
- }
140
- }
141
-
142
- setIsOpen(false);
143
- },
144
- [allCommands, navigate]
145
- );
146
-
147
- // Keyboard shortcut: Cmd+K / Ctrl+K
148
- React.useEffect(() => {
149
- const handleKeyDown = (e: KeyboardEvent) => {
150
- if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
151
- e.preventDefault();
152
- setIsOpen((prev) => !prev);
153
- }
154
- };
155
-
156
- window.addEventListener('keydown', handleKeyDown);
157
- return () => window.removeEventListener('keydown', handleKeyDown);
158
- }, []);
159
-
160
- const value = React.useMemo(
161
- () => ({
162
- open: () => setIsOpen(true),
163
- close: () => setIsOpen(false),
164
- toggle: () => setIsOpen((prev) => !prev),
165
- isOpen,
166
- }),
167
- [isOpen]
168
- );
169
-
170
- return (
171
- <CommandPaletteContext.Provider value={value}>
172
- {children}
173
- <KBQuickSearch
174
- open={isOpen}
175
- onClose={() => setIsOpen(false)}
176
- items={items}
177
- onNavigate={handleNavigate}
178
- placeholder="Search pages, run commands..."
179
- />
180
- </CommandPaletteContext.Provider>
181
- );
182
- }
183
-
184
- /**
185
- * Hook to use command palette
186
- */
187
- export function useCommandPalette() {
188
- const context = React.useContext(CommandPaletteContext);
189
- if (!context) {
190
- throw new Error('useCommandPalette must be used within CommandPaletteProvider');
191
- }
192
- return context;
193
- }
@@ -1,27 +0,0 @@
1
- import { createContext, useContext, useMemo, type ReactNode } from 'react';
2
- import { createDataSources, type DataSources } from '@kb-labs/studio-data-client';
3
- import { studioConfig } from '@/config/studio.config';
4
-
5
- const DataSourcesContext = createContext<DataSources | null>(null);
6
-
7
- export function DataSourcesProvider({ children }: { children: ReactNode }) {
8
- const sources = useMemo(
9
- () => createDataSources({
10
- mode: studioConfig.dataSourceMode,
11
- baseUrl: studioConfig.apiBaseUrl,
12
- token: studioConfig.gatewayToken,
13
- }),
14
- [],
15
- );
16
-
17
- return <DataSourcesContext.Provider value={sources}>{children}</DataSourcesContext.Provider>;
18
- }
19
-
20
- export function useDataSources() {
21
- const context = useContext(DataSourcesContext);
22
- if (!context) {
23
- throw new Error('useDataSources must be used within DataSourcesProvider');
24
- }
25
- return context;
26
- }
27
-
@@ -1,72 +0,0 @@
1
- import { useEffect, useRef, type ReactNode } from 'react';
2
- import { devToolsStore, GenericChannel } from '@kb-labs/studio-devtools';
3
- import type { DevToolsPlugin, EventBusEvent } from '@kb-labs/studio-devtools';
4
- import { eventBus } from '@kb-labs/studio-event-bus';
5
- import { useFeatureFlags } from '@/hooks/use-feature-flags';
6
-
7
- interface DevToolsProviderProps {
8
- children: ReactNode;
9
- /** External plugins to register alongside built-in channels */
10
- plugins?: DevToolsPlugin[];
11
- }
12
-
13
- /**
14
- * Mounts all DevTools instrumentation when the 'devtools-panel' feature flag is enabled.
15
- * Must be placed inside SettingsProvider (for feature flags) and outside RegistryV2Provider
16
- * (so MF events from registry load are captured).
17
- */
18
- export function DevToolsProvider({ children, plugins = [] }: DevToolsProviderProps) {
19
- const { isEnabled } = useFeatureFlags();
20
- const enabled = isEnabled('devtools-panel');
21
- const pluginsRef = useRef(plugins);
22
- pluginsRef.current = plugins;
23
-
24
- useEffect(() => {
25
- if (!enabled) { return; }
26
-
27
- // --- EventBus channel ---
28
- const eventBusChannel = new GenericChannel<EventBusEvent>(
29
- 'eventbus',
30
- 'EventBus',
31
- 'NodeIndexOutlined',
32
- );
33
- devToolsStore.registerChannel(eventBusChannel);
34
-
35
- // Backfill existing history
36
- eventBus.getHistory().forEach((record) => {
37
- eventBusChannel.push({
38
- id: `eb-${record.meta.timestamp}-${Math.random().toString(36).slice(2)}`,
39
- event: record.event,
40
- payload: record.payload,
41
- sourcePluginId: record.meta.sourcePluginId,
42
- sourcePageId: record.meta.sourcePageId,
43
- timestamp: record.meta.timestamp,
44
- });
45
- });
46
-
47
- // Live stream
48
- eventBus.setDevToolsObserver((record) => {
49
- eventBusChannel.push({
50
- id: `eb-${record.meta.timestamp}-${Math.random().toString(36).slice(2)}`,
51
- event: record.event,
52
- payload: record.payload,
53
- sourcePluginId: record.meta.sourcePluginId,
54
- sourcePageId: record.meta.sourcePageId,
55
- timestamp: record.meta.timestamp,
56
- });
57
- });
58
-
59
- // --- External plugins ---
60
- pluginsRef.current.forEach((p) => { devToolsStore.registerPlugin(p); });
61
-
62
- return () => {
63
- eventBus.clearDevToolsObserver();
64
- devToolsStore.unregisterChannel('eventbus');
65
- pluginsRef.current.forEach((p) => {
66
- devToolsStore.unregisterChannel(p.channel.id);
67
- });
68
- };
69
- }, [enabled]);
70
-
71
- return <>{children}</>;
72
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * @module @kb-labs/studio-app/providers/navigation-items-provider
3
- * Provides the list of available sidebar navigation items to settings UI.
4
- * Single source of truth — no hardcoded item lists.
5
- */
6
-
7
- import * as React from 'react';
8
-
9
- export interface NavigationItemDescriptor {
10
- key: string;
11
- label: string;
12
- }
13
-
14
- interface NavigationItemsContextValue {
15
- availableItems: NavigationItemDescriptor[];
16
- }
17
-
18
- const NavigationItemsContext = React.createContext<NavigationItemsContextValue>({
19
- availableItems: [],
20
- });
21
-
22
- export interface NavigationItemsProviderProps {
23
- items: NavigationItemDescriptor[];
24
- children: React.ReactNode;
25
- }
26
-
27
- export function NavigationItemsProvider({ items, children }: NavigationItemsProviderProps) {
28
- const value = React.useMemo(() => ({ availableItems: items }), [items]);
29
- return (
30
- <NavigationItemsContext.Provider value={value}>
31
- {children}
32
- </NavigationItemsContext.Provider>
33
- );
34
- }
35
-
36
- export function useNavigationItems(): NavigationItemDescriptor[] {
37
- return React.useContext(NavigationItemsContext).availableItems;
38
- }