@workbench-kit/react 0.0.1-prototype.0 → 0.0.2-prototype.0.1.1

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 (155) hide show
  1. package/package.json +33 -9
  2. package/src/index.ts +545 -43
  3. package/src/jdw/JdwPreview.tsx +38 -0
  4. package/src/jdw/JsonCodeEditorPane.tsx +274 -0
  5. package/src/jdw/builtins/renderBuiltinWidgetLeaf.tsx +29 -0
  6. package/src/jdw/builtins/renderBuiltinWidgetNode.tsx +126 -0
  7. package/src/jdw/createBuiltinJdwRegistry.ts +111 -0
  8. package/src/jdw/cssRenderBackend.tsx +134 -0
  9. package/src/jdw/document.ts +38 -0
  10. package/src/jdw/fixtures/jdw-fixtures.ts +52 -0
  11. package/src/jdw/fixtures/jdw-sample-screens.ts +522 -0
  12. package/src/jdw/index.ts +45 -0
  13. package/src/jdw/parse.ts +1 -0
  14. package/src/jdw/renderJdw.tsx +32 -0
  15. package/src/json-config/JsonConfigWorkbench.tsx +316 -0
  16. package/src/json-config/index.ts +6 -0
  17. package/src/json-config/json-config-editor-state.ts +42 -0
  18. package/src/layout/Panel.tsx +146 -1
  19. package/src/layout/SideBarViewFrame.tsx +367 -328
  20. package/src/layout/WorkbenchCanvas.tsx +849 -0
  21. package/src/layout/WorkbenchFullscreen.tsx +368 -0
  22. package/src/layout/WorkbenchLayout.tsx +5 -0
  23. package/src/layout/WorkbenchLayoutBase.tsx +294 -0
  24. package/src/layout/WorkbenchPropertyPanel.tsx +497 -0
  25. package/src/layout/WorkbenchSidebarActions.tsx +274 -0
  26. package/src/layout/WorkbenchTree.tsx +351 -0
  27. package/src/layout/layoutHelpers.ts +25 -0
  28. package/src/modal/ConfirmDialog.tsx +61 -53
  29. package/src/modal/Modal.tsx +295 -35
  30. package/src/overlay/ContextMenu.tsx +146 -145
  31. package/src/primitives/AbsoluteBox.tsx +46 -0
  32. package/src/primitives/Badge.tsx +12 -12
  33. package/src/primitives/Button.tsx +44 -14
  34. package/src/primitives/Checkbox.tsx +11 -5
  35. package/src/primitives/EmptyState.tsx +27 -26
  36. package/src/primitives/Field.tsx +38 -38
  37. package/src/primitives/IconButton.tsx +5 -2
  38. package/src/primitives/List.tsx +111 -0
  39. package/src/primitives/NumberInput.tsx +38 -0
  40. package/src/primitives/ScrollArea.tsx +42 -0
  41. package/src/primitives/Select.tsx +1 -12
  42. package/src/primitives/StatusBar.tsx +46 -0
  43. package/src/primitives/TextArea.tsx +36 -0
  44. package/src/primitives/TextInput.tsx +11 -2
  45. package/src/primitives/WorkbenchChrome.tsx +424 -0
  46. package/src/primitives/WorkbenchEditor.tsx +394 -0
  47. package/src/primitives/index.ts +105 -0
  48. package/src/primitives/select/Select.tsx +266 -0
  49. package/src/primitives/select/index.ts +2 -0
  50. package/src/primitives/select/options.ts +38 -0
  51. package/src/primitives/select/overlay.ts +63 -0
  52. package/src/primitives/select/select.app.css +9 -0
  53. package/src/primitives/select/select.css +140 -0
  54. package/src/primitives/select/types.ts +18 -0
  55. package/src/primitives/styles.css +955 -0
  56. package/src/scrollbars.css +69 -0
  57. package/src/styles.css +7738 -1762
  58. package/src/utils/codicon.ts +17 -0
  59. package/src/widget-asset/WidgetAssetEditor.tsx +140 -0
  60. package/src/widget-asset/WidgetAssetMetadataForm.tsx +82 -0
  61. package/src/widget-asset/WidgetAssetModeControls.tsx +42 -0
  62. package/src/widget-asset/WidgetAssetSourceEditor.tsx +50 -0
  63. package/src/widget-asset/WidgetAssetWorkbench.tsx +112 -0
  64. package/src/widget-asset/index.ts +17 -0
  65. package/src/widget-asset/widget-asset-document.ts +37 -0
  66. package/src/widget-asset/widget-asset-mode.ts +3 -0
  67. package/src/widget-studio/builtin-widget-asset-catalog.ts +12 -0
  68. package/src/widget-studio/create-widget-studio-workspace-editor.tsx +79 -0
  69. package/src/widget-studio/index.ts +7 -0
  70. package/src/widget-studio/resolve-widget-studio-asset-catalog.ts +26 -0
  71. package/src/widget-tree/WidgetAssetPalette.tsx +77 -0
  72. package/src/widget-tree/WidgetInspectorPanel.tsx +266 -0
  73. package/src/widget-tree/WidgetSourceEditor.tsx +56 -0
  74. package/src/widget-tree/WidgetTreeLab.tsx +272 -0
  75. package/src/widget-tree/WidgetTreeModeControls.tsx +44 -0
  76. package/src/widget-tree/WidgetTreeSidePanel.tsx +49 -0
  77. package/src/widget-tree/WidgetTreeView.tsx +97 -0
  78. package/src/widget-tree/WidgetTreeWorkbench.tsx +111 -0
  79. package/src/widget-tree/WidgetTreeWorkspaceShell.tsx +154 -0
  80. package/src/widget-tree/demo-registry.ts +32 -0
  81. package/src/widget-tree/demo-widget-assets.ts +4 -0
  82. package/src/widget-tree/index.ts +27 -0
  83. package/src/widget-tree/widget-tree-document.ts +20 -0
  84. package/src/widget-tree/widget-tree-layout.ts +31 -0
  85. package/src/widget-tree/widget-tree-mode.ts +7 -0
  86. package/src/widget-tree/widget-tree-play-helpers.ts +74 -0
  87. package/src/workbench/ActivityBar.tsx +52 -52
  88. package/src/workbench/ArtifactShell.tsx +397 -0
  89. package/src/workbench/CommandPalette.tsx +819 -0
  90. package/src/workbench/ConfirmationFlow.tsx +245 -0
  91. package/src/workbench/MarkdownPreview.tsx +151 -0
  92. package/src/workbench/ShortcutCommandBridge.tsx +368 -0
  93. package/src/workbench/SplitView.tsx +136 -136
  94. package/src/workbench/StatusBar.tsx +178 -123
  95. package/src/workbench/StructuredArtifactEditor.tsx +205 -0
  96. package/src/workbench/Timeline.tsx +302 -0
  97. package/src/workbench/WorkbenchCanvasShell.tsx +941 -0
  98. package/src/workbench/WorkbenchShell.tsx +74 -70
  99. package/src/workbench/WorkbenchStandaloneShell.tsx +318 -291
  100. package/src/workbench/auth/WorkbenchAuthGate.tsx +61 -0
  101. package/src/workbench/auth/WorkbenchLoginView.tsx +635 -0
  102. package/src/workbench/auth/index.ts +19 -0
  103. package/src/workbench/chat/ChatComposer.tsx +165 -148
  104. package/src/workbench/chat/ChatMessageItem.tsx +10 -1
  105. package/src/workbench/chat/index.ts +9 -0
  106. package/src/workbench/chat/slashCommand.ts +28 -0
  107. package/src/workbench/chat/useChatRuntimeState.ts +76 -0
  108. package/src/workbench/chat/useSlashCommandSuggest.ts +101 -0
  109. package/src/workbench/commands.ts +520 -490
  110. package/src/workbench/index.ts +443 -98
  111. package/src/workbench/keyboard.ts +53 -0
  112. package/src/workbench/schema/index.ts +48 -0
  113. package/src/workbench/schema/workbenchDocument.ts +31 -0
  114. package/src/workbench/schema/workbenchDocumentActions.ts +6 -0
  115. package/src/workbench/schema/workbenchDocumentAdapter.ts +9 -0
  116. package/src/workbench/schema/workbenchDocumentPatch.ts +13 -0
  117. package/src/workbench/schema/workbenchDocumentRenderer.tsx +702 -0
  118. package/src/workbench/settings/NavigationPanel.tsx +47 -0
  119. package/src/workbench/settings/SchemaForm.tsx +420 -0
  120. package/src/workbench/settings/SectionedPanel.tsx +415 -0
  121. package/src/workbench/settings/StructuredDataForm.tsx +539 -0
  122. package/src/workbench/settings/StructuredDataSchemaPanel.tsx +559 -0
  123. package/src/workbench/settings/StructuredDataSchemaPanelEmbed.tsx +21 -0
  124. package/src/workbench/settings/StructuredDataSchemaPanelFrame.tsx +76 -0
  125. package/src/workbench/settings/StructuredDataTableView.tsx +127 -0
  126. package/src/workbench/settings/WorkbenchPanelRegion.tsx +46 -0
  127. package/src/workbench/settings/WorkbenchSettingsModal.tsx +21 -12
  128. package/src/workbench/settings/WorkbenchSettingsNav.tsx +38 -22
  129. package/src/workbench/settings/index.ts +135 -0
  130. package/src/workbench/settings/panel-region.css +21 -0
  131. package/src/workbench/settings/sectionedPanelScrollSpy.ts +143 -0
  132. package/src/workbench/settings/structured-data-schema-panel.css +330 -0
  133. package/src/workbench/settings/structured-data-table-view.css +85 -0
  134. package/src/workbench/settings/structuredDataSchema.ts +886 -0
  135. package/src/workbench/shell.ts +15 -0
  136. package/src/workbench/shellState.ts +203 -203
  137. package/src/workbench/standalone.ts +101 -94
  138. package/src/workbench/status.ts +129 -0
  139. package/src/workbench/theme.ts +44 -0
  140. package/src/workbench/workspace/MultiProviderExplorer.tsx +625 -0
  141. package/src/workbench/workspace/WorkspaceDraftsContext.tsx +111 -0
  142. package/src/workbench/workspace/WorkspaceEditor.tsx +47 -12
  143. package/src/workbench/workspace/WorkspaceEditorPanel.tsx +334 -353
  144. package/src/workbench/workspace/WorkspaceExplorer.tsx +532 -524
  145. package/src/workbench/workspace/WorkspaceFileIcon.tsx +32 -2
  146. package/src/workbench/workspace/WorkspaceSearchPanel.tsx +113 -113
  147. package/src/workbench/workspace/WorkspaceSearchResults.tsx +47 -47
  148. package/src/workbench/workspace/index.ts +156 -98
  149. package/src/workbench/workspace/mimeType.ts +45 -0
  150. package/src/workbench/workspace/path.ts +10 -10
  151. package/src/workbench/workspace/search.ts +6 -6
  152. package/src/workbench/workspace/tree.ts +1 -1
  153. package/src/workbench/workspace/types.ts +10 -10
  154. package/src/workbench/workspace/useVirtualWorkspace.ts +111 -98
  155. package/src/workbench/workspace/workspaceJsonDiagnostics.ts +83 -0
@@ -0,0 +1,15 @@
1
+ export { ActivityBar } from './ActivityBar';
2
+ export type { ActivityBarItem, ActivityBarProps } from './ActivityBar';
3
+ export { SplitView } from './SplitView';
4
+ export type { SplitViewProps } from './SplitView';
5
+ export { StatusBar, StatusBarItem, StatusBarSection } from './StatusBar';
6
+ export type {
7
+ StatusBarItemModel,
8
+ StatusBarItemProps,
9
+ StatusBarProps,
10
+ StatusBarSectionAlign,
11
+ StatusBarSectionModel,
12
+ StatusBarSectionProps,
13
+ } from './StatusBar';
14
+ export { WorkbenchShell } from './WorkbenchShell';
15
+ export type { WorkbenchShellProps } from './WorkbenchShell';
@@ -1,203 +1,203 @@
1
- import { useReducer } from 'react';
2
-
3
- export interface WorkbenchShellInitialState<
4
- TActivityId extends string = string,
5
- TTheme extends string = string,
6
- > {
7
- activeActivityId: TActivityId;
8
- isPrimarySidebarVisible?: boolean;
9
- isSettingsOpen?: boolean;
10
- primarySidebarSizePercent?: number;
11
- settingsCategoryId?: string;
12
- settingsScopeId?: string;
13
- settingsSearchValue?: string;
14
- theme: TTheme;
15
- }
16
-
17
- export interface WorkbenchShellState<
18
- TActivityId extends string = string,
19
- TTheme extends string = string,
20
- > {
21
- activeActivityId: TActivityId;
22
- isPrimarySidebarVisible: boolean;
23
- isSettingsOpen: boolean;
24
- primarySidebarSizePercent: number;
25
- settingsCategoryId: string;
26
- settingsScopeId: string;
27
- settingsSearchValue: string;
28
- theme: TTheme;
29
- }
30
-
31
- export type WorkbenchShellAction<
32
- TActivityId extends string = string,
33
- TTheme extends string = string,
34
- > =
35
- | { activityId: TActivityId; type: 'activate-activity' }
36
- | { activityId: TActivityId; type: 'show-activity' }
37
- | { isOpen: boolean; type: 'set-settings-open' }
38
- | { percent: number; type: 'set-primary-sidebar-size' }
39
- | { settingsCategoryId: string; type: 'set-settings-category' }
40
- | { settingsScopeId: string; type: 'set-settings-scope' }
41
- | { settingsSearchValue: string; type: 'set-settings-search' }
42
- | { theme: TTheme; type: 'set-theme' }
43
- | { type: 'close-settings' }
44
- | { type: 'open-settings' }
45
- | { type: 'toggle-primary-sidebar' }
46
- | { isVisible: boolean; type: 'set-primary-sidebar-visible' };
47
-
48
- export interface UseWorkbenchShellStateResult<
49
- TActivityId extends string = string,
50
- TTheme extends string = string,
51
- > {
52
- activateActivity: (activityId: TActivityId) => void;
53
- closeSettings: () => void;
54
- dispatch: (action: WorkbenchShellAction<TActivityId, TTheme>) => void;
55
- openSettings: () => void;
56
- setPrimarySidebarSizePercent: (percent: number) => void;
57
- setPrimarySidebarVisible: (isVisible: boolean) => void;
58
- setSettingsCategoryId: (settingsCategoryId: string) => void;
59
- setSettingsOpen: (isOpen: boolean) => void;
60
- setSettingsScopeId: (settingsScopeId: string) => void;
61
- setSettingsSearchValue: (settingsSearchValue: string) => void;
62
- setTheme: (theme: TTheme) => void;
63
- showActivity: (activityId: TActivityId) => void;
64
- state: WorkbenchShellState<TActivityId, TTheme>;
65
- togglePrimarySidebar: () => void;
66
- }
67
-
68
- const DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT = 24;
69
- const MIN_PRIMARY_SIDEBAR_SIZE_PERCENT = 10;
70
- const MAX_PRIMARY_SIDEBAR_SIZE_PERCENT = 90;
71
-
72
- function clampPrimarySidebarSizePercent(percent: number, fallback: number) {
73
- if (!Number.isFinite(percent)) return fallback;
74
- return Math.min(
75
- MAX_PRIMARY_SIDEBAR_SIZE_PERCENT,
76
- Math.max(MIN_PRIMARY_SIDEBAR_SIZE_PERCENT, percent),
77
- );
78
- }
79
-
80
- export function initializeWorkbenchShellState<TActivityId extends string, TTheme extends string>({
81
- activeActivityId,
82
- isPrimarySidebarVisible = true,
83
- isSettingsOpen = false,
84
- primarySidebarSizePercent = DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT,
85
- settingsCategoryId = '',
86
- settingsScopeId = '',
87
- settingsSearchValue = '',
88
- theme,
89
- }: WorkbenchShellInitialState<TActivityId, TTheme>): WorkbenchShellState<TActivityId, TTheme> {
90
- return {
91
- activeActivityId,
92
- isPrimarySidebarVisible,
93
- isSettingsOpen,
94
- primarySidebarSizePercent: clampPrimarySidebarSizePercent(
95
- primarySidebarSizePercent,
96
- DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT,
97
- ),
98
- settingsCategoryId,
99
- settingsScopeId,
100
- settingsSearchValue,
101
- theme,
102
- };
103
- }
104
-
105
- export function workbenchShellStateReducer<TActivityId extends string, TTheme extends string>(
106
- state: WorkbenchShellState<TActivityId, TTheme>,
107
- action: WorkbenchShellAction<TActivityId, TTheme>,
108
- ): WorkbenchShellState<TActivityId, TTheme> {
109
- if (action.type === 'activate-activity') {
110
- const shouldHideSidebar =
111
- action.activityId === state.activeActivityId && state.isPrimarySidebarVisible;
112
-
113
- return {
114
- ...state,
115
- activeActivityId: action.activityId,
116
- isPrimarySidebarVisible: !shouldHideSidebar,
117
- };
118
- }
119
-
120
- if (action.type === 'show-activity') {
121
- return {
122
- ...state,
123
- activeActivityId: action.activityId,
124
- isPrimarySidebarVisible: true,
125
- };
126
- }
127
-
128
- if (action.type === 'set-primary-sidebar-visible') {
129
- return { ...state, isPrimarySidebarVisible: action.isVisible };
130
- }
131
-
132
- if (action.type === 'toggle-primary-sidebar') {
133
- return { ...state, isPrimarySidebarVisible: !state.isPrimarySidebarVisible };
134
- }
135
-
136
- if (action.type === 'set-primary-sidebar-size') {
137
- return {
138
- ...state,
139
- primarySidebarSizePercent: clampPrimarySidebarSizePercent(
140
- action.percent,
141
- state.primarySidebarSizePercent,
142
- ),
143
- };
144
- }
145
-
146
- if (action.type === 'set-theme') {
147
- return { ...state, theme: action.theme };
148
- }
149
-
150
- if (action.type === 'open-settings') {
151
- return { ...state, isSettingsOpen: true };
152
- }
153
-
154
- if (action.type === 'close-settings') {
155
- return { ...state, isSettingsOpen: false };
156
- }
157
-
158
- if (action.type === 'set-settings-open') {
159
- return { ...state, isSettingsOpen: action.isOpen };
160
- }
161
-
162
- if (action.type === 'set-settings-category') {
163
- return { ...state, settingsCategoryId: action.settingsCategoryId };
164
- }
165
-
166
- if (action.type === 'set-settings-scope') {
167
- return { ...state, settingsScopeId: action.settingsScopeId };
168
- }
169
-
170
- return { ...state, settingsSearchValue: action.settingsSearchValue };
171
- }
172
-
173
- export function useWorkbenchShellState<TActivityId extends string, TTheme extends string>(
174
- initialState: WorkbenchShellInitialState<TActivityId, TTheme>,
175
- ): UseWorkbenchShellStateResult<TActivityId, TTheme> {
176
- const [state, dispatch] = useReducer(
177
- workbenchShellStateReducer<TActivityId, TTheme>,
178
- initialState,
179
- initializeWorkbenchShellState,
180
- );
181
-
182
- return {
183
- activateActivity: (activityId) => dispatch({ activityId, type: 'activate-activity' }),
184
- closeSettings: () => dispatch({ type: 'close-settings' }),
185
- dispatch,
186
- openSettings: () => dispatch({ type: 'open-settings' }),
187
- setPrimarySidebarSizePercent: (percent) =>
188
- dispatch({ percent, type: 'set-primary-sidebar-size' }),
189
- setPrimarySidebarVisible: (isVisible) =>
190
- dispatch({ isVisible, type: 'set-primary-sidebar-visible' }),
191
- setSettingsCategoryId: (settingsCategoryId) =>
192
- dispatch({ settingsCategoryId, type: 'set-settings-category' }),
193
- setSettingsOpen: (isOpen) => dispatch({ isOpen, type: 'set-settings-open' }),
194
- setSettingsScopeId: (settingsScopeId) =>
195
- dispatch({ settingsScopeId, type: 'set-settings-scope' }),
196
- setSettingsSearchValue: (settingsSearchValue) =>
197
- dispatch({ settingsSearchValue, type: 'set-settings-search' }),
198
- setTheme: (theme) => dispatch({ theme, type: 'set-theme' }),
199
- showActivity: (activityId) => dispatch({ activityId, type: 'show-activity' }),
200
- state,
201
- togglePrimarySidebar: () => dispatch({ type: 'toggle-primary-sidebar' }),
202
- };
203
- }
1
+ import { useReducer } from 'react';
2
+
3
+ export interface WorkbenchShellInitialState<
4
+ TActivityId extends string = string,
5
+ TTheme extends string = string,
6
+ > {
7
+ activeActivityId: TActivityId;
8
+ isPrimarySidebarVisible?: boolean;
9
+ isSettingsOpen?: boolean;
10
+ primarySidebarSizePercent?: number;
11
+ settingsCategoryId?: string;
12
+ settingsScopeId?: string;
13
+ settingsSearchValue?: string;
14
+ theme: TTheme;
15
+ }
16
+
17
+ export interface WorkbenchShellState<
18
+ TActivityId extends string = string,
19
+ TTheme extends string = string,
20
+ > {
21
+ activeActivityId: TActivityId;
22
+ isPrimarySidebarVisible: boolean;
23
+ isSettingsOpen: boolean;
24
+ primarySidebarSizePercent: number;
25
+ settingsCategoryId: string;
26
+ settingsScopeId: string;
27
+ settingsSearchValue: string;
28
+ theme: TTheme;
29
+ }
30
+
31
+ export type WorkbenchShellAction<
32
+ TActivityId extends string = string,
33
+ TTheme extends string = string,
34
+ > =
35
+ | { activityId: TActivityId; type: 'activate-activity' }
36
+ | { activityId: TActivityId; type: 'show-activity' }
37
+ | { isOpen: boolean; type: 'set-settings-open' }
38
+ | { percent: number; type: 'set-primary-sidebar-size' }
39
+ | { settingsCategoryId: string; type: 'set-settings-category' }
40
+ | { settingsScopeId: string; type: 'set-settings-scope' }
41
+ | { settingsSearchValue: string; type: 'set-settings-search' }
42
+ | { theme: TTheme; type: 'set-theme' }
43
+ | { type: 'close-settings' }
44
+ | { type: 'open-settings' }
45
+ | { type: 'toggle-primary-sidebar' }
46
+ | { isVisible: boolean; type: 'set-primary-sidebar-visible' };
47
+
48
+ export interface UseWorkbenchShellStateResult<
49
+ TActivityId extends string = string,
50
+ TTheme extends string = string,
51
+ > {
52
+ activateActivity: (activityId: TActivityId) => void;
53
+ closeSettings: () => void;
54
+ dispatch: (action: WorkbenchShellAction<TActivityId, TTheme>) => void;
55
+ openSettings: () => void;
56
+ setPrimarySidebarSizePercent: (percent: number) => void;
57
+ setPrimarySidebarVisible: (isVisible: boolean) => void;
58
+ setSettingsCategoryId: (settingsCategoryId: string) => void;
59
+ setSettingsOpen: (isOpen: boolean) => void;
60
+ setSettingsScopeId: (settingsScopeId: string) => void;
61
+ setSettingsSearchValue: (settingsSearchValue: string) => void;
62
+ setTheme: (theme: TTheme) => void;
63
+ showActivity: (activityId: TActivityId) => void;
64
+ state: WorkbenchShellState<TActivityId, TTheme>;
65
+ togglePrimarySidebar: () => void;
66
+ }
67
+
68
+ export const DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT = 20;
69
+ const MIN_PRIMARY_SIDEBAR_SIZE_PERCENT = 10;
70
+ const MAX_PRIMARY_SIDEBAR_SIZE_PERCENT = 90;
71
+
72
+ function clampPrimarySidebarSizePercent(percent: number, fallback: number) {
73
+ if (!Number.isFinite(percent)) return fallback;
74
+ return Math.min(
75
+ MAX_PRIMARY_SIDEBAR_SIZE_PERCENT,
76
+ Math.max(MIN_PRIMARY_SIDEBAR_SIZE_PERCENT, percent),
77
+ );
78
+ }
79
+
80
+ export function initializeWorkbenchShellState<TActivityId extends string, TTheme extends string>({
81
+ activeActivityId,
82
+ isPrimarySidebarVisible = true,
83
+ isSettingsOpen = false,
84
+ primarySidebarSizePercent = DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT,
85
+ settingsCategoryId = '',
86
+ settingsScopeId = '',
87
+ settingsSearchValue = '',
88
+ theme,
89
+ }: WorkbenchShellInitialState<TActivityId, TTheme>): WorkbenchShellState<TActivityId, TTheme> {
90
+ return {
91
+ activeActivityId,
92
+ isPrimarySidebarVisible,
93
+ isSettingsOpen,
94
+ primarySidebarSizePercent: clampPrimarySidebarSizePercent(
95
+ primarySidebarSizePercent,
96
+ DEFAULT_PRIMARY_SIDEBAR_SIZE_PERCENT,
97
+ ),
98
+ settingsCategoryId,
99
+ settingsScopeId,
100
+ settingsSearchValue,
101
+ theme,
102
+ };
103
+ }
104
+
105
+ export function workbenchShellStateReducer<TActivityId extends string, TTheme extends string>(
106
+ state: WorkbenchShellState<TActivityId, TTheme>,
107
+ action: WorkbenchShellAction<TActivityId, TTheme>,
108
+ ): WorkbenchShellState<TActivityId, TTheme> {
109
+ if (action.type === 'activate-activity') {
110
+ const shouldHideSidebar =
111
+ action.activityId === state.activeActivityId && state.isPrimarySidebarVisible;
112
+
113
+ return {
114
+ ...state,
115
+ activeActivityId: action.activityId,
116
+ isPrimarySidebarVisible: !shouldHideSidebar,
117
+ };
118
+ }
119
+
120
+ if (action.type === 'show-activity') {
121
+ return {
122
+ ...state,
123
+ activeActivityId: action.activityId,
124
+ isPrimarySidebarVisible: true,
125
+ };
126
+ }
127
+
128
+ if (action.type === 'set-primary-sidebar-visible') {
129
+ return { ...state, isPrimarySidebarVisible: action.isVisible };
130
+ }
131
+
132
+ if (action.type === 'toggle-primary-sidebar') {
133
+ return { ...state, isPrimarySidebarVisible: !state.isPrimarySidebarVisible };
134
+ }
135
+
136
+ if (action.type === 'set-primary-sidebar-size') {
137
+ return {
138
+ ...state,
139
+ primarySidebarSizePercent: clampPrimarySidebarSizePercent(
140
+ action.percent,
141
+ state.primarySidebarSizePercent,
142
+ ),
143
+ };
144
+ }
145
+
146
+ if (action.type === 'set-theme') {
147
+ return { ...state, theme: action.theme };
148
+ }
149
+
150
+ if (action.type === 'open-settings') {
151
+ return { ...state, isSettingsOpen: true };
152
+ }
153
+
154
+ if (action.type === 'close-settings') {
155
+ return { ...state, isSettingsOpen: false };
156
+ }
157
+
158
+ if (action.type === 'set-settings-open') {
159
+ return { ...state, isSettingsOpen: action.isOpen };
160
+ }
161
+
162
+ if (action.type === 'set-settings-category') {
163
+ return { ...state, settingsCategoryId: action.settingsCategoryId };
164
+ }
165
+
166
+ if (action.type === 'set-settings-scope') {
167
+ return { ...state, settingsScopeId: action.settingsScopeId };
168
+ }
169
+
170
+ return { ...state, settingsSearchValue: action.settingsSearchValue };
171
+ }
172
+
173
+ export function useWorkbenchShellState<TActivityId extends string, TTheme extends string>(
174
+ initialState: WorkbenchShellInitialState<TActivityId, TTheme>,
175
+ ): UseWorkbenchShellStateResult<TActivityId, TTheme> {
176
+ const [state, dispatch] = useReducer(
177
+ workbenchShellStateReducer<TActivityId, TTheme>,
178
+ initialState,
179
+ initializeWorkbenchShellState,
180
+ );
181
+
182
+ return {
183
+ activateActivity: (activityId) => dispatch({ activityId, type: 'activate-activity' }),
184
+ closeSettings: () => dispatch({ type: 'close-settings' }),
185
+ dispatch,
186
+ openSettings: () => dispatch({ type: 'open-settings' }),
187
+ setPrimarySidebarSizePercent: (percent) =>
188
+ dispatch({ percent, type: 'set-primary-sidebar-size' }),
189
+ setPrimarySidebarVisible: (isVisible) =>
190
+ dispatch({ isVisible, type: 'set-primary-sidebar-visible' }),
191
+ setSettingsCategoryId: (settingsCategoryId) =>
192
+ dispatch({ settingsCategoryId, type: 'set-settings-category' }),
193
+ setSettingsOpen: (isOpen) => dispatch({ isOpen, type: 'set-settings-open' }),
194
+ setSettingsScopeId: (settingsScopeId) =>
195
+ dispatch({ settingsScopeId, type: 'set-settings-scope' }),
196
+ setSettingsSearchValue: (settingsSearchValue) =>
197
+ dispatch({ settingsSearchValue, type: 'set-settings-search' }),
198
+ setTheme: (theme) => dispatch({ theme, type: 'set-theme' }),
199
+ showActivity: (activityId) => dispatch({ activityId, type: 'show-activity' }),
200
+ state,
201
+ togglePrimarySidebar: () => dispatch({ type: 'toggle-primary-sidebar' }),
202
+ };
203
+ }
@@ -1,94 +1,101 @@
1
- import type { CommandRegistry } from '@workbench-kit/core';
2
- import type {
3
- SaveResult,
4
- WorkspacePatchApplyResult,
5
- WorkspacePatchEvent,
6
- } from '@workbench-kit/contracts';
7
- import type { ReactNode } from 'react';
8
- import type { StatusBarSectionModel } from './StatusBar';
9
- import type { WorkbenchShellCommandContext } from './commands';
10
- import type { WorkspaceFile } from './workspace';
11
-
12
- export type WorkbenchTheme = 'light' | 'dark' | (string & {});
13
-
14
- export interface WorkbenchActivityDescriptor<TActivityId extends string = string> {
15
- id: TActivityId;
16
- label: string;
17
- icon?: string;
18
- iconNode?: ReactNode;
19
- }
20
-
21
- export interface WorkbenchActivityChangeEvent<TActivityId extends string = string> {
22
- nextActivityId: TActivityId;
23
- }
24
-
25
- export interface WorkbenchWorkspaceController {
26
- openFile: (path: string) => void | Promise<void>;
27
- saveFile: (path: string, content: string, previousUpdatedAt?: string) => Promise<SaveResult>;
28
- deleteFiles: (paths: string[]) => void | Promise<void>;
29
- moveFiles?: (paths: string[], targetParentPath: string | undefined) => void | Promise<void>;
30
- rename?: (path: string, nextName: string) => void | Promise<void>;
31
- }
32
-
33
- export interface WorkbenchChatController {
34
- onChatSubmit: (message: string, context?: Record<string, unknown>) => void | Promise<void>;
35
- onCancelChat: () => void;
36
- }
37
-
38
- export interface WorkbenchPatchController {
39
- onPatchApply: (patch: WorkspacePatchEvent) => Promise<WorkspacePatchApplyResult> | void;
40
- }
41
-
42
- export interface WorkbenchSaveController {
43
- onSaveResult?: (result: SaveResult) => void | Promise<void>;
44
- onCommitPatchResult?: (
45
- patch: WorkspacePatchEvent,
46
- result: WorkspacePatchApplyResult,
47
- source: 'chat' | 'command',
48
- ) => void | Promise<void>;
49
- }
50
-
51
- export interface WorkbenchStatusController {
52
- onStatusMessage?: (message: string) => void;
53
- onError?: (error: Error) => void;
54
- }
55
-
56
- export interface WorkbenchShellContract<TActivityId extends string = string> {
57
- activities: WorkbenchActivityDescriptor<TActivityId>[];
58
- commandRegistry: CommandRegistry<WorkbenchShellCommandContext<TActivityId>>;
59
- initialActivityId?: TActivityId;
60
- initialTheme?: WorkbenchTheme;
61
- statusSections: StatusBarSectionModel[];
62
- statusCompact?: boolean;
63
- }
64
-
65
- export interface WorkbenchStandaloneEntryState<TActivityId extends string = string> {
66
- activeActivityId: TActivityId;
67
- isPrimarySidebarVisible: boolean;
68
- primarySidebarSizePercent: number;
69
- primarySidebarMinPercent?: number;
70
- primarySidebarMaxPercent?: number;
71
- theme: WorkbenchTheme;
72
- isSettingsOpen?: boolean;
73
- settingsCategoryId?: string;
74
- settingsScopeId?: string;
75
- settingsSearchValue?: string;
76
- selectedFilePath?: string;
77
- openFilePaths?: readonly string[];
78
- }
79
-
80
- export interface WorkbenchStandaloneBootstrap<TActivityId extends string = string> {
81
- contract: WorkbenchShellContract<TActivityId>;
82
- initialFiles: readonly WorkspaceFile[];
83
- workspace: WorkbenchWorkspaceController;
84
- chat: WorkbenchChatController;
85
- patch: WorkbenchPatchController;
86
- save: WorkbenchSaveController;
87
- status: WorkbenchStatusController;
88
- initialState?: Partial<WorkbenchStandaloneEntryState<TActivityId>>;
89
- }
90
-
91
- export type WorkbenchStandaloneBootstrapEvent<TActivityId extends string = string> =
92
- | { type: 'activity-change'; payload: WorkbenchActivityChangeEvent<TActivityId> }
93
- | { type: 'status-message'; message: string }
94
- | { type: 'error'; error: Error };
1
+ import type { CommandRegistry } from '@workbench-kit/platform';
2
+ import type {
3
+ SaveResult,
4
+ WorkspacePatchApplyResult,
5
+ WorkspacePatchEvent,
6
+ } from '@workbench-kit/contracts';
7
+ import type { ReactNode } from 'react';
8
+ import type { StatusBarSectionModel } from './StatusBar';
9
+ import type { WorkbenchShellCommandContext } from './commands';
10
+ import type { WorkspaceFile } from './workspace';
11
+
12
+ export type WorkbenchTheme = 'light' | 'dark' | (string & {});
13
+
14
+ export interface WorkbenchActivityDescriptor<TActivityId extends string = string> {
15
+ id: TActivityId;
16
+ label: string;
17
+ icon?: string;
18
+ iconNode?: ReactNode;
19
+ }
20
+
21
+ export interface WorkbenchActivityChangeEvent<TActivityId extends string = string> {
22
+ nextActivityId: TActivityId;
23
+ }
24
+
25
+ export interface WorkbenchWorkspaceController {
26
+ openFile: (path: string) => void | Promise<void>;
27
+ saveFile: (path: string, content: string, previousUpdatedAt?: string) => Promise<SaveResult>;
28
+ deleteFiles: (paths: string[]) => void | Promise<void>;
29
+ moveFiles?: (paths: string[], targetParentPath: string | undefined) => void | Promise<void>;
30
+ rename?: (path: string, nextName: string) => void | Promise<void>;
31
+ }
32
+
33
+ export interface WorkbenchHostCallbackBoundary {
34
+ onSave?: (path: string, content: string, previousUpdatedAt?: string) => Promise<SaveResult>;
35
+ onDelete?: (paths: readonly string[]) => void | Promise<void>;
36
+ onChatSubmit?: (message: string, context?: Record<string, unknown>) => void | Promise<void>;
37
+ onPatch?: (patch: WorkspacePatchEvent) => Promise<WorkspacePatchApplyResult> | void;
38
+ }
39
+
40
+ export interface WorkbenchChatController {
41
+ onChatSubmit: (message: string, context?: Record<string, unknown>) => void | Promise<void>;
42
+ onCancelChat: () => void;
43
+ }
44
+
45
+ export interface WorkbenchPatchController {
46
+ onPatchApply: (patch: WorkspacePatchEvent) => Promise<WorkspacePatchApplyResult> | void;
47
+ }
48
+
49
+ export interface WorkbenchSaveController {
50
+ onSaveResult?: (result: SaveResult) => void | Promise<void>;
51
+ onCommitPatchResult?: (
52
+ patch: WorkspacePatchEvent,
53
+ result: WorkspacePatchApplyResult,
54
+ source: 'chat' | 'command',
55
+ ) => void | Promise<void>;
56
+ }
57
+
58
+ export interface WorkbenchStatusController {
59
+ onStatusMessage?: (message: string) => void;
60
+ onError?: (error: Error) => void;
61
+ }
62
+
63
+ export interface WorkbenchShellContract<TActivityId extends string = string> {
64
+ activities: WorkbenchActivityDescriptor<TActivityId>[];
65
+ commandRegistry: CommandRegistry<WorkbenchShellCommandContext<TActivityId>>;
66
+ initialActivityId?: TActivityId;
67
+ initialTheme?: WorkbenchTheme;
68
+ statusSections: StatusBarSectionModel[];
69
+ statusCompact?: boolean;
70
+ }
71
+
72
+ export interface WorkbenchStandaloneEntryState<TActivityId extends string = string> {
73
+ activeActivityId: TActivityId;
74
+ isPrimarySidebarVisible: boolean;
75
+ primarySidebarSizePercent: number;
76
+ primarySidebarMinPercent?: number;
77
+ primarySidebarMaxPercent?: number;
78
+ theme: WorkbenchTheme;
79
+ isSettingsOpen?: boolean;
80
+ settingsCategoryId?: string;
81
+ settingsScopeId?: string;
82
+ settingsSearchValue?: string;
83
+ selectedFilePath?: string;
84
+ openFilePaths?: readonly string[];
85
+ }
86
+
87
+ export interface WorkbenchStandaloneBootstrap<TActivityId extends string = string> {
88
+ contract: WorkbenchShellContract<TActivityId>;
89
+ initialFiles: readonly WorkspaceFile[];
90
+ workspace: WorkbenchWorkspaceController;
91
+ chat: WorkbenchChatController;
92
+ patch: WorkbenchPatchController;
93
+ save: WorkbenchSaveController;
94
+ status: WorkbenchStatusController;
95
+ initialState?: Partial<WorkbenchStandaloneEntryState<TActivityId>>;
96
+ }
97
+
98
+ export type WorkbenchStandaloneBootstrapEvent<TActivityId extends string = string> =
99
+ | { type: 'activity-change'; payload: WorkbenchActivityChangeEvent<TActivityId> }
100
+ | { type: 'status-message'; message: string }
101
+ | { type: 'error'; error: Error };