@maka/maka-cli 5.1.41 → 5.1.43

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 (61) hide show
  1. package/.claude/settings.local.json +4 -1
  2. package/bundle/typescript/package.json +8 -2
  3. package/bundle/typescript/src/commands/_index.d.ts +1 -1
  4. package/bundle/typescript/src/commands/_index.js +1 -1
  5. package/bundle/typescript/src/commands/_index.js.map +1 -1
  6. package/bundle/typescript/src/commands/ai/_index.d.ts +2 -0
  7. package/bundle/typescript/src/commands/ai/_index.js +3 -0
  8. package/bundle/typescript/src/commands/ai/_index.js.map +1 -0
  9. package/bundle/typescript/src/commands/ai/ai.command.d.ts +3 -0
  10. package/bundle/typescript/src/commands/{ai.js → ai/ai.command.js} +9 -7
  11. package/bundle/typescript/src/commands/ai/ai.command.js.map +1 -0
  12. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js +605 -0
  13. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js.map +1 -0
  14. package/bundle/typescript/src/commands/create.js +79 -35
  15. package/bundle/typescript/src/commands/create.js.map +1 -1
  16. package/bundle/typescript/src/generators/api.js +3 -1
  17. package/bundle/typescript/src/generators/api.js.map +1 -1
  18. package/bundle/typescript/src/generators/component.js +3 -1
  19. package/bundle/typescript/src/generators/component.js.map +1 -1
  20. package/bundle/typescript/src/generators/hook.js +3 -1
  21. package/bundle/typescript/src/generators/hook.js.map +1 -1
  22. package/bundle/typescript/src/generators/kits/_index.d.ts +1 -0
  23. package/bundle/typescript/src/generators/kits/_index.js +1 -0
  24. package/bundle/typescript/src/generators/kits/_index.js.map +1 -1
  25. package/bundle/typescript/src/generators/kits/frames/_index.d.ts +1 -0
  26. package/bundle/typescript/src/generators/kits/frames/_index.js +2 -0
  27. package/bundle/typescript/src/generators/kits/frames/_index.js.map +1 -0
  28. package/bundle/typescript/src/generators/kits/frames/frames.generator.d.ts +3 -0
  29. package/bundle/typescript/src/generators/kits/frames/frames.generator.js +166 -0
  30. package/bundle/typescript/src/generators/kits/frames/frames.generator.js.map +1 -0
  31. package/bundle/typescript/src/generators/kits/mui/auth.mui.gen.js +3 -2
  32. package/bundle/typescript/src/generators/kits/mui/auth.mui.gen.js.map +1 -1
  33. package/bundle/typescript/src/generators/layout.js +3 -1
  34. package/bundle/typescript/src/generators/layout.js.map +1 -1
  35. package/bundle/typescript/src/generators/package.js +3 -1
  36. package/bundle/typescript/src/generators/package.js.map +1 -1
  37. package/bundle/typescript/src/generators/page.js +3 -1
  38. package/bundle/typescript/src/generators/page.js.map +1 -1
  39. package/bundle/typescript/src/templates/meteor/template/template-tests.js.jsx +2 -2
  40. package/bundle/typescript/src/templates/meteor/template/template-tests.js.tsx +2 -2
  41. package/bundle/typescript/src/templates/meteor/template/template.js.jsx +2 -2
  42. package/bundle/typescript/src/templates/meteor/template/template.js.tsx +2 -2
  43. package/bundle/typescript/src/templates/react/hook/hook.js.jsx +1 -1
  44. package/bundle/typescript/src/templates/react/kit/auth/service/meteor-auth-service.js.jsx +4 -2
  45. package/bundle/typescript/src/templates/react/kit/frames/frames-demo.css +63 -0
  46. package/bundle/typescript/src/templates/react/kit/frames/frames-demo.jsx +153 -0
  47. package/bundle/typescript/src/templates/react/kit/frames/frames-demo.tsx +164 -0
  48. package/bundle/typescript/src/templates/react/kit/frames/workspace-manager.css +105 -0
  49. package/bundle/typescript/src/templates/react/kit/frames/workspace-manager.jsx +158 -0
  50. package/bundle/typescript/src/templates/react/kit/frames/workspace-manager.tsx +166 -0
  51. package/bundle/typescript/src/templates/react/kit/mui/auth/login/basic-login-page.js.jsx +3 -1
  52. package/bundle/typescript/src/templates/react/kit/mui/auth/login/basic-login-page.js.tsx +3 -1
  53. package/bundle/typescript/src/templates/react/test/test.js.jsx +2 -2
  54. package/bundle/typescript/src/templates/react/test/test.js.tsx +2 -2
  55. package/bundle/typescript/src/tools/fsi/fsi.interfaces.d.ts +3 -0
  56. package/bundle/typescript/src/tools/fsi/fsi.interfaces.js +3 -1
  57. package/bundle/typescript/src/tools/fsi/fsi.interfaces.js.map +1 -1
  58. package/docs/MCP_SERVER.md +396 -0
  59. package/package.json +8 -2
  60. package/bundle/typescript/src/commands/ai.js.map +0 -1
  61. /package/bundle/typescript/src/commands/{ai.d.ts → ai/mcp.sub.cmd.d.ts} +0 -0
@@ -0,0 +1,153 @@
1
+ import './<%= fileName %>.css';
2
+ import React, { Component } from 'react';
3
+ import { withTracker } from 'meteor/maka:react-tracker';
4
+ import { Frame, FramesContainer, Workspace, FrameManagerBar } from 'meteor/maka:maka-frames';
5
+ import { WorkspaceManagerComponent } from '../../components/workspace-manager/workspace-manager';
6
+ import PropTypes from 'prop-types';
7
+
8
+ class <%= className %> extends Component {
9
+ static propTypes = {};
10
+
11
+ static defaultProps = {};
12
+
13
+ constructor(props) {
14
+ super(props);
15
+ this.state = {
16
+ currentWorkspaceId: 'demo-workspace',
17
+ showFrameManager: true
18
+ };
19
+ }
20
+
21
+ toggleFrameManager = () => {
22
+ this.setState({ showFrameManager: !this.state.showFrameManager });
23
+ }
24
+
25
+ handleWorkspaceSwitch = (workspaceId) => {
26
+ this.setState({ currentWorkspaceId: workspaceId });
27
+ }
28
+
29
+ // Custom frame menu items
30
+ getFrameMenuItems = () => {
31
+ return [];
32
+ }
33
+
34
+ // Workspace context menu items
35
+ getWorkspaceMenuItems = (toggleFrame, resetWorkspace) => {
36
+ return [
37
+ {
38
+ label: 'New Frame',
39
+ icon: '➕',
40
+ action: () => {
41
+ const newId = `demo-frame-${Date.now()}`;
42
+ toggleFrame(newId, {
43
+ title: 'New Frame',
44
+ x: Math.random() * 300 + 100,
45
+ y: Math.random() * 300 + 100,
46
+ width: 400,
47
+ height: 300
48
+ });
49
+ }
50
+ },
51
+ { divider: true },
52
+ {
53
+ label: 'Reset Workspace',
54
+ icon: '🔄',
55
+ action: () => {
56
+ resetWorkspace();
57
+ }
58
+ }
59
+ ];
60
+ }
61
+
62
+ render() {
63
+ const { currentWorkspaceId } = this.state;
64
+
65
+ return (
66
+ <Workspace
67
+ workspaceId={currentWorkspaceId}
68
+ workspaceName={currentWorkspaceId === 'demo-workspace' ? 'Demo Workspace' : `Workspace ${currentWorkspaceId.split('-')[1]}`}
69
+ contextMenuItems={this.getFrameMenuItems()}
70
+ enableContextMenu={true}
71
+ workspaceContextMenuItems={({ toggleFrame, resetWorkspace }) => this.getWorkspaceMenuItems(toggleFrame, resetWorkspace)}
72
+ enableWorkspaceContextMenu={true}
73
+ >
74
+ {({ workspace, allWorkspaces, updateFrame, handleFrameMenu, handleWorkspaceContextMenu, minimizeFrame, onFrameManagerClick, onFrameManagerClose }) => {
75
+ return (
76
+ <div id="<%= fileName %>">
77
+ <div className="<%= fileName %>-header">
78
+ <h1>Maka Frames Demo</h1>
79
+
80
+ <WorkspaceManagerComponent
81
+ currentWorkspaceId={this.state.currentWorkspaceId}
82
+ allWorkspaces={allWorkspaces}
83
+ user={this.props.user}
84
+ onWorkspaceSwitch={this.handleWorkspaceSwitch}
85
+ />
86
+
87
+ <button onClick={this.toggleFrameManager} style={{ padding: '8px 16px', cursor: 'pointer', borderRadius: '4px', border: 'none', background: '#fff', fontWeight: 'bold' }}>
88
+ {this.state.showFrameManager ? 'Hide' : 'Show'} Toolbar
89
+ </button>
90
+ </div>
91
+
92
+ <FramesContainer
93
+ className="frames-container"
94
+ onContextMenu={handleWorkspaceContextMenu}
95
+ >
96
+ {/* Render all frames dynamically */}
97
+ {workspace.frames.map(frame => (
98
+ frame.display && (
99
+ <Frame
100
+ key={frame.id}
101
+ id={frame.id}
102
+ title={frame.title}
103
+ x={frame.x}
104
+ y={frame.y}
105
+ width={frame.width}
106
+ height={frame.height}
107
+ display={frame.display}
108
+ zIndex={frame.zIndex}
109
+ onMenuClick={handleFrameMenu}
110
+ onFrameUpdate={updateFrame}
111
+ onMinimize={minimizeFrame}
112
+ >
113
+ <div className="frame-content">
114
+ <h3>{frame.title}</h3>
115
+ <p>Frame content goes here.</p>
116
+ <p>ID: <code>{frame.id}</code></p>
117
+ <p>Position: ({frame.x}, {frame.y})</p>
118
+ <p>Size: {frame.width} × {frame.height}</p>
119
+ </div>
120
+ </Frame>
121
+ )
122
+ ))
123
+ }
124
+ </FramesContainer>
125
+ {this.state.showFrameManager && (
126
+ <FrameManagerBar
127
+ workspace={workspace}
128
+ allWorkspaces={allWorkspaces}
129
+ onFrameClick={onFrameManagerClick}
130
+ onFrameClose={onFrameManagerClose}
131
+ onWorkspaceClick={this.handleWorkspaceSwitch}
132
+ position="bottom"
133
+ showClosed={true}
134
+ maxItems={20}
135
+ />
136
+ )}
137
+ </div>
138
+ );
139
+ }}
140
+ </Workspace>
141
+ );
142
+ }
143
+ }
144
+
145
+ const <%= className %>WithData = withTracker(() => {
146
+ const user = Meteor.user();
147
+
148
+ return {
149
+ user
150
+ };
151
+ })(<%= className %>);
152
+
153
+ export { <%= className %>WithData as <%= className %> };
@@ -0,0 +1,164 @@
1
+ import './<%= fileName %>.css';
2
+ import * as React from 'react';
3
+ import { Component } from 'react';
4
+ import { withTracker } from 'meteor/maka:react-tracker';
5
+ import { Frame, FramesContainer, Workspace, FrameManagerBar } from 'meteor/maka:maka-frames';
6
+ import { WorkspaceManagerComponent } from '../../components/workspace-manager/workspace-manager';
7
+ import PropTypes from 'prop-types';
8
+
9
+ interface <%= className %>Props {
10
+ user?: any;
11
+ allWorkspaces: any[];
12
+ }
13
+
14
+ interface <%= className %>State {
15
+ currentWorkspaceId: string;
16
+ showFrameManager: boolean;
17
+ }
18
+
19
+ class <%= className %> extends Component<<%= className %>Props, <%= className %>State> {
20
+ static propTypes = {};
21
+
22
+ static defaultProps = {};
23
+
24
+ constructor(props: <%= className %>Props) {
25
+ super(props);
26
+ this.state = {
27
+ currentWorkspaceId: 'demo-workspace',
28
+ showFrameManager: true
29
+ };
30
+ }
31
+
32
+ toggleFrameManager = () => {
33
+ this.setState({ showFrameManager: !this.state.showFrameManager });
34
+ }
35
+
36
+ handleWorkspaceSwitch = (workspaceId: string) => {
37
+ this.setState({ currentWorkspaceId: workspaceId });
38
+ }
39
+
40
+ // Custom frame menu items
41
+ getFrameMenuItems = () => {
42
+ return [];
43
+ }
44
+
45
+ // Workspace context menu items
46
+ getWorkspaceMenuItems = (toggleFrame: any, resetWorkspace: any) => {
47
+ return [
48
+ {
49
+ label: 'New Frame',
50
+ icon: '➕',
51
+ action: () => {
52
+ const newId = `demo-frame-${Date.now()}`;
53
+ toggleFrame(newId, {
54
+ title: 'New Frame',
55
+ x: Math.random() * 300 + 100,
56
+ y: Math.random() * 300 + 100,
57
+ width: 400,
58
+ height: 300
59
+ });
60
+ }
61
+ },
62
+ { divider: true },
63
+ {
64
+ label: 'Reset Workspace',
65
+ icon: '🔄',
66
+ action: () => {
67
+ resetWorkspace();
68
+ }
69
+ }
70
+ ];
71
+ }
72
+
73
+ render() {
74
+ const { currentWorkspaceId } = this.state;
75
+
76
+ return (
77
+ <Workspace
78
+ workspaceId={currentWorkspaceId}
79
+ workspaceName={currentWorkspaceId === 'demo-workspace' ? 'Demo Workspace' : `Workspace ${currentWorkspaceId.split('-')[1]}`}
80
+ contextMenuItems={this.getFrameMenuItems()}
81
+ enableContextMenu={true}
82
+ workspaceContextMenuItems={({ toggleFrame, resetWorkspace }) => this.getWorkspaceMenuItems(toggleFrame, resetWorkspace)}
83
+ enableWorkspaceContextMenu={true}
84
+ >
85
+ {({ workspace, allWorkspaces, updateFrame, handleFrameMenu, handleWorkspaceContextMenu, minimizeFrame, onFrameManagerClick, onFrameManagerClose }) => {
86
+ return (
87
+ <div id="<%= fileName %>">
88
+ <div className="<%= fileName %>-header">
89
+ <h1>Maka Frames Demo</h1>
90
+
91
+ <WorkspaceManagerComponent
92
+ currentWorkspaceId={this.state.currentWorkspaceId}
93
+ allWorkspaces={allWorkspaces}
94
+ user={this.props.user}
95
+ onWorkspaceSwitch={this.handleWorkspaceSwitch}
96
+ />
97
+
98
+ <button onClick={this.toggleFrameManager} style={{ padding: '8px 16px', cursor: 'pointer', borderRadius: '4px', border: 'none', background: '#fff', fontWeight: 'bold' }}>
99
+ {this.state.showFrameManager ? 'Hide' : 'Show'} Toolbar
100
+ </button>
101
+ </div>
102
+
103
+ <FramesContainer
104
+ className="frames-container"
105
+ onContextMenu={handleWorkspaceContextMenu}
106
+ >
107
+ {/* Render all frames dynamically */}
108
+ {workspace.frames.map((frame: any) => (
109
+ frame.display && (
110
+ <Frame
111
+ key={frame.id}
112
+ id={frame.id}
113
+ title={frame.title}
114
+ x={frame.x}
115
+ y={frame.y}
116
+ width={frame.width}
117
+ height={frame.height}
118
+ display={frame.display}
119
+ zIndex={frame.zIndex}
120
+ onMenuClick={handleFrameMenu}
121
+ onFrameUpdate={updateFrame}
122
+ onMinimize={minimizeFrame}
123
+ >
124
+ <div className="frame-content">
125
+ <h3>{frame.title}</h3>
126
+ <p>Frame content goes here.</p>
127
+ <p>ID: <code>{frame.id}</code></p>
128
+ <p>Position: ({frame.x}, {frame.y})</p>
129
+ <p>Size: {frame.width} × {frame.height}</p>
130
+ </div>
131
+ </Frame>
132
+ )
133
+ ))
134
+ }
135
+ </FramesContainer>
136
+ {this.state.showFrameManager && (
137
+ <FrameManagerBar
138
+ workspace={workspace}
139
+ allWorkspaces={allWorkspaces}
140
+ onFrameClick={onFrameManagerClick}
141
+ onFrameClose={onFrameManagerClose}
142
+ onWorkspaceClick={this.handleWorkspaceSwitch}
143
+ position="bottom"
144
+ showClosed={true}
145
+ maxItems={20}
146
+ />
147
+ )}
148
+ </div>
149
+ );
150
+ }}
151
+ </Workspace>
152
+ );
153
+ }
154
+ }
155
+
156
+ const <%= className %>WithData = withTracker(() => {
157
+ const user = Meteor.user();
158
+
159
+ return {
160
+ user
161
+ };
162
+ })(<%= className %>);
163
+
164
+ export { <%= className %>WithData as <%= className %> };
@@ -0,0 +1,105 @@
1
+ .<%= fileName %> {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 15px;
5
+ flex-wrap: wrap;
6
+ }
7
+
8
+ .workspace-selector {
9
+ display: flex;
10
+ align-items: center;
11
+ }
12
+
13
+ .workspace-select {
14
+ padding: 8px 12px;
15
+ border: 2px solid #667eea;
16
+ border-radius: 4px;
17
+ background: white;
18
+ font-size: 14px;
19
+ font-weight: 500;
20
+ color: #333;
21
+ cursor: pointer;
22
+ transition: all 0.2s ease;
23
+ min-width: 180px;
24
+ }
25
+
26
+ .workspace-select:hover {
27
+ border-color: #764ba2;
28
+ box-shadow: 0 2px 4px rgba(102, 126, 234, 0.2);
29
+ }
30
+
31
+ .workspace-select:focus {
32
+ outline: none;
33
+ border-color: #764ba2;
34
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
35
+ }
36
+
37
+ .workspace-actions {
38
+ display: flex;
39
+ gap: 10px;
40
+ flex-wrap: wrap;
41
+ }
42
+
43
+ .workspace-btn {
44
+ padding: 8px 16px;
45
+ border: none;
46
+ border-radius: 4px;
47
+ font-size: 14px;
48
+ font-weight: 500;
49
+ cursor: pointer;
50
+ transition: all 0.2s ease;
51
+ white-space: nowrap;
52
+ }
53
+
54
+ .workspace-create-btn {
55
+ background: #667eea;
56
+ color: white;
57
+ }
58
+
59
+ .workspace-create-btn:hover {
60
+ background: #5568d3;
61
+ box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);
62
+ }
63
+
64
+ .workspace-rename-btn {
65
+ background: #48bb78;
66
+ color: white;
67
+ }
68
+
69
+ .workspace-rename-btn:hover {
70
+ background: #38a169;
71
+ box-shadow: 0 2px 4px rgba(72, 187, 120, 0.3);
72
+ }
73
+
74
+ .workspace-delete-btn {
75
+ background: #f56565;
76
+ color: white;
77
+ }
78
+
79
+ .workspace-delete-btn:hover {
80
+ background: #e53e3e;
81
+ box-shadow: 0 2px 4px rgba(245, 101, 101, 0.3);
82
+ }
83
+
84
+ .workspace-btn:active {
85
+ transform: translateY(1px);
86
+ }
87
+
88
+ @media (max-width: 768px) {
89
+ .<%= fileName %> {
90
+ flex-direction: column;
91
+ align-items: stretch;
92
+ }
93
+
94
+ .workspace-select {
95
+ width: 100%;
96
+ }
97
+
98
+ .workspace-actions {
99
+ width: 100%;
100
+ }
101
+
102
+ .workspace-btn {
103
+ flex: 1;
104
+ }
105
+ }
@@ -0,0 +1,158 @@
1
+ import './<%= fileName %>.css';
2
+ import React, { Component } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { WorkspaceManager, WorkspaceStore } from 'meteor/maka:maka-frames';
5
+
6
+ /**
7
+ * <%= className %> Component
8
+ *
9
+ * UI component for managing workspaces in the maka-frames package.
10
+ * Provides controls for creating, switching, renaming, and deleting workspaces.
11
+ */
12
+ class <%= className %>Component extends Component {
13
+ static propTypes = {
14
+ currentWorkspaceId: PropTypes.string.isRequired,
15
+ allWorkspaces: PropTypes.array.isRequired,
16
+ user: PropTypes.object,
17
+ onWorkspaceSwitch: PropTypes.func
18
+ };
19
+
20
+ handleCreateWorkspace = () => {
21
+ const { user, onWorkspaceSwitch } = this.props;
22
+
23
+ const workspaceName = prompt('Enter workspace name:', `Workspace ${new Date().toLocaleTimeString()}`);
24
+ if (!workspaceName) return;
25
+
26
+ const workspaceId = `workspace-${Date.now()}`;
27
+ const workspaceData = {
28
+ id: workspaceId,
29
+ name: workspaceName,
30
+ frames: [],
31
+ createdAt: new Date(),
32
+ updatedAt: new Date()
33
+ };
34
+
35
+ // Use WorkspaceManager for logged-in users, WorkspaceStore for anonymous
36
+ if (user) {
37
+ WorkspaceManager.createWorkspace(workspaceData.id, workspaceData.name)
38
+ .then(() => {
39
+ console.log('Workspace created:', workspaceData.id);
40
+ if (onWorkspaceSwitch) onWorkspaceSwitch(workspaceData.id);
41
+ })
42
+ .catch((error) => {
43
+ console.error('Error creating workspace:', error);
44
+ });
45
+ } else {
46
+ WorkspaceStore.setWorkspace(workspaceData);
47
+ if (onWorkspaceSwitch) onWorkspaceSwitch(workspaceData.id);
48
+ }
49
+ }
50
+
51
+ handleDeleteWorkspace = (workspaceId) => {
52
+ const { user, allWorkspaces, onWorkspaceSwitch } = this.props;
53
+
54
+ const workspace = allWorkspaces.find(ws => ws.id === workspaceId);
55
+ if (!workspace) return;
56
+
57
+ const confirmed = confirm(`Are you sure you want to delete "${workspace.name}"?`);
58
+ if (!confirmed) return;
59
+
60
+ // Use WorkspaceManager for logged-in users, WorkspaceStore for anonymous
61
+ if (user) {
62
+ WorkspaceManager.deleteWorkspace(workspaceId)
63
+ .then(() => {
64
+ console.log('Workspace deleted:', workspaceId);
65
+ // Switch to first available workspace
66
+ const remainingWorkspaces = allWorkspaces.filter(ws => ws.id !== workspaceId);
67
+ if (remainingWorkspaces.length > 0 && onWorkspaceSwitch) {
68
+ onWorkspaceSwitch(remainingWorkspaces[0].id);
69
+ }
70
+ })
71
+ .catch((error) => {
72
+ // Handle error (e.g., last workspace can't be deleted)
73
+ alert(error.message || 'Cannot delete workspace');
74
+ console.error('Error deleting workspace:', error);
75
+ });
76
+ } else {
77
+ const success = WorkspaceStore.deleteWorkspace(workspaceId);
78
+ if (success) {
79
+ // Switch to first available workspace
80
+ const remainingWorkspaces = allWorkspaces.filter(ws => ws.id !== workspaceId);
81
+ if (remainingWorkspaces.length > 0 && onWorkspaceSwitch) {
82
+ onWorkspaceSwitch(remainingWorkspaces[0].id);
83
+ }
84
+ } else {
85
+ alert('Cannot delete the last workspace');
86
+ }
87
+ }
88
+ }
89
+
90
+ handleRenameWorkspace = (workspaceId) => {
91
+ const { user, allWorkspaces } = this.props;
92
+
93
+ const workspace = allWorkspaces.find(ws => ws.id === workspaceId);
94
+ if (!workspace) return;
95
+
96
+ const newName = prompt('Enter new workspace name:', workspace.name);
97
+ if (!newName || newName === workspace.name) return;
98
+
99
+ // Use WorkspaceManager for logged-in users, WorkspaceStore for anonymous
100
+ if (user) {
101
+ WorkspaceManager.updateWorkspace(workspaceId, { name: newName });
102
+ } else {
103
+ const localWorkspace = WorkspaceStore.getWorkspace(workspaceId);
104
+ if (localWorkspace) {
105
+ localWorkspace.name = newName;
106
+ localWorkspace.updatedAt = new Date();
107
+ WorkspaceStore.setWorkspace(localWorkspace);
108
+ }
109
+ }
110
+ }
111
+
112
+ render() {
113
+ const { currentWorkspaceId, allWorkspaces, onWorkspaceSwitch } = this.props;
114
+
115
+ return (
116
+ <div className="<%= fileName %>">
117
+ <div className="workspace-selector">
118
+ <select
119
+ value={currentWorkspaceId}
120
+ onChange={(e) => onWorkspaceSwitch && onWorkspaceSwitch(e.target.value)}
121
+ className="workspace-select"
122
+ >
123
+ {allWorkspaces.map(ws => (
124
+ <option key={ws.id} value={ws.id}>{ws.name}</option>
125
+ ))}
126
+ </select>
127
+ </div>
128
+
129
+ <div className="workspace-actions">
130
+ <button
131
+ onClick={this.handleCreateWorkspace}
132
+ className="workspace-btn workspace-create-btn"
133
+ >
134
+ + New Workspace
135
+ </button>
136
+
137
+ <button
138
+ onClick={() => this.handleRenameWorkspace(currentWorkspaceId)}
139
+ className="workspace-btn workspace-rename-btn"
140
+ >
141
+ Rename Workspace
142
+ </button>
143
+
144
+ {allWorkspaces.length > 1 && (
145
+ <button
146
+ onClick={() => this.handleDeleteWorkspace(currentWorkspaceId)}
147
+ className="workspace-btn workspace-delete-btn"
148
+ >
149
+ Delete Workspace
150
+ </button>
151
+ )}
152
+ </div>
153
+ </div>
154
+ );
155
+ }
156
+ }
157
+
158
+ export { <%= className %>Component };