@teambit/workspace 0.0.567 → 0.0.571

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 (64) hide show
  1. package/__snapshots__/pick-outdated-pkgs.spec.ts.snap +88 -0
  2. package/component-config-file/component-config-file.ts +98 -0
  3. package/component-config-file/exceptions/already-exists.ts +7 -0
  4. package/component-config-file/exceptions/index.ts +1 -0
  5. package/component-config-file/index.ts +2 -0
  6. package/component-tree.widget.tsx +16 -0
  7. package/dist/__snapshots__/pick-outdated-pkgs.spec.js.snap +88 -0
  8. package/dist/__snapshots__/pick-outdated-pkgs.spec.ts.snap +88 -0
  9. package/dist/pick-outdated-pkgs.d.ts +12 -0
  10. package/dist/pick-outdated-pkgs.js +201 -0
  11. package/dist/pick-outdated-pkgs.js.map +1 -0
  12. package/dist/pick-outdated-pkgs.spec.d.ts +1 -0
  13. package/dist/pick-outdated-pkgs.spec.js +64 -0
  14. package/dist/pick-outdated-pkgs.spec.js.map +1 -0
  15. package/dist/update.cmd.js +3 -5
  16. package/dist/update.cmd.js.map +1 -1
  17. package/dist/workspace.d.ts +8 -1
  18. package/dist/workspace.js +29 -3
  19. package/dist/workspace.js.map +1 -1
  20. package/eject-conf.cmd.tsx +62 -0
  21. package/events/index.ts +3 -0
  22. package/events/on-component-add-event.ts +14 -0
  23. package/events/on-component-change-event.ts +14 -0
  24. package/events/on-component-removed-event.ts +14 -0
  25. package/exceptions/dependency-type-not-supported-in-policy.ts +7 -0
  26. package/exceptions/incorrect-env-aspect.ts +8 -0
  27. package/exceptions/index.ts +1 -0
  28. package/install.cmd.tsx +67 -0
  29. package/link/component-list-links.ts +50 -0
  30. package/link/core-aspects-links.ts +50 -0
  31. package/link/get-package-name-from-target.ts +5 -0
  32. package/link/index.ts +1 -0
  33. package/link/link-row.ts +20 -0
  34. package/link/link-to-dir.ts +13 -0
  35. package/link/link.cmd.ts +96 -0
  36. package/link/nested-deps-in-nm-links.ts +47 -0
  37. package/link/rewire-row.ts +17 -0
  38. package/list.cmd.tsx +30 -0
  39. package/package-tar/teambit-workspace-0.0.571.tgz +0 -0
  40. package/package.json +54 -65
  41. package/types/asset.d.ts +29 -0
  42. package/types/style.d.ts +42 -0
  43. package/ui/index.ts +1 -0
  44. package/ui/workspace/default-component.ts +7 -0
  45. package/ui/workspace/index.ts +1 -0
  46. package/ui/workspace/use-workspace.ts +193 -0
  47. package/ui/workspace/workspace-context.tsx +5 -0
  48. package/ui/workspace/workspace-model.ts +66 -0
  49. package/ui/workspace/workspace-overview/index.ts +1 -0
  50. package/ui/workspace/workspace-overview/workspace-overview.tsx +21 -0
  51. package/ui/workspace/workspace-provider.tsx +23 -0
  52. package/ui/workspace/workspace.tsx +99 -0
  53. package/ui/workspace-components-drawer/index.ts +1 -0
  54. package/ui/workspace-components-drawer/workspace-components.drawer.tsx +49 -0
  55. package/update.cmd.tsx +30 -0
  56. package/watch/check-types.ts +5 -0
  57. package/watch/output-formatter.ts +50 -0
  58. package/watch/watch.cmd.tsx +142 -0
  59. package/watch/watcher.ts +289 -0
  60. package/workspace-component/component-status.ts +67 -0
  61. package/workspace-component/index.ts +2 -0
  62. package/workspace-component/workspace-component-loader.ts +276 -0
  63. package/workspace-component/workspace-component.ts +51 -0
  64. package/workspace.ui.runtime.tsx +215 -0
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@teambit/workspace",
3
- "version": "0.0.567",
3
+ "version": "0.0.571",
4
4
  "homepage": "https://bit.dev/teambit/workspace/workspace",
5
5
  "main": "dist/index.js",
6
6
  "componentId": {
7
7
  "scope": "teambit.workspace",
8
8
  "name": "workspace",
9
- "version": "0.0.567"
9
+ "version": "0.0.571"
10
10
  },
11
11
  "dependencies": {
12
12
  "lodash.compact": "3.0.1",
@@ -14,6 +14,10 @@
14
14
  "p-map-series": "2.1.0",
15
15
  "chalk": "2.4.2",
16
16
  "ink": "3.0.8",
17
+ "@pnpm/colorize-semver-diff": "1.0.1",
18
+ "@pnpm/semver-diff": "1.1.0",
19
+ "enquirer": "2.3.6",
20
+ "table": "5.4.6",
17
21
  "semver": "7.3.4",
18
22
  "@teambit/harmony": "0.2.11",
19
23
  "graphql-tag": "2.12.1",
@@ -34,55 +38,55 @@
34
38
  "@teambit/base-ui.surfaces.split-pane.hover-splitter": "1.0.0",
35
39
  "@teambit/base-ui.surfaces.split-pane.split-pane": "1.0.0",
36
40
  "@teambit/base-ui.graph.tree.recursive-tree": "1.0.0",
37
- "@teambit/bit-error": "0.0.379",
38
- "@teambit/legacy-bit-id": "0.0.382",
39
- "@teambit/logger": "0.0.479",
40
- "@teambit/scope": "0.0.567",
41
- "@teambit/cli": "0.0.393",
42
- "@teambit/isolator": "0.0.567",
43
- "@teambit/component-tree": "0.0.379",
44
- "@teambit/component.ui.component-status-resolver": "0.0.474",
45
- "@teambit/harmony.modules.resolved-component": "0.0.468",
46
- "@teambit/dependency-resolver": "0.0.567",
47
- "@teambit/compiler": "0.0.567",
48
- "@teambit/component": "0.0.567",
49
- "@teambit/graphql": "0.0.567",
50
- "@teambit/aspect-loader": "0.0.567",
51
- "@teambit/bundler": "0.0.567",
52
- "@teambit/envs": "0.0.567",
53
- "@teambit/pubsub": "0.0.567",
54
- "@teambit/ui": "0.0.567",
55
- "@teambit/variants": "0.0.481",
56
- "@teambit/component-issues": "0.0.28",
57
- "@teambit/config": "0.0.405",
58
- "@teambit/harmony.modules.requireable-component": "0.0.468",
59
- "@teambit/importer": "0.0.20",
60
- "@teambit/workspace.modules.match-pattern": "0.0.472",
61
- "@teambit/command-bar": "0.0.567",
41
+ "@teambit/bit-error": "0.0.381",
42
+ "@teambit/legacy-bit-id": "0.0.384",
43
+ "@teambit/logger": "0.0.483",
44
+ "@teambit/scope": "0.0.571",
45
+ "@teambit/cli": "0.0.395",
46
+ "@teambit/isolator": "0.0.571",
47
+ "@teambit/component-tree": "0.0.381",
48
+ "@teambit/component.ui.component-status-resolver": "0.0.476",
49
+ "@teambit/harmony.modules.resolved-component": "0.0.470",
50
+ "@teambit/dependency-resolver": "0.0.571",
51
+ "@teambit/compiler": "0.0.571",
52
+ "@teambit/component": "0.0.571",
53
+ "@teambit/graphql": "0.0.571",
54
+ "@teambit/aspect-loader": "0.0.571",
55
+ "@teambit/bundler": "0.0.571",
56
+ "@teambit/envs": "0.0.571",
57
+ "@teambit/pubsub": "0.0.571",
58
+ "@teambit/ui": "0.0.571",
59
+ "@teambit/variants": "0.0.485",
60
+ "@teambit/component-issues": "0.0.30",
61
+ "@teambit/config": "0.0.407",
62
+ "@teambit/harmony.modules.requireable-component": "0.0.470",
63
+ "@teambit/importer": "0.0.22",
64
+ "@teambit/workspace.modules.match-pattern": "0.0.474",
65
+ "@teambit/command-bar": "0.0.571",
62
66
  "@teambit/design.ui.surfaces.menu.link-item": "0.0.374",
63
- "@teambit/graph": "0.0.567",
64
- "@teambit/react-router": "0.0.567",
65
- "@teambit/sidebar": "0.0.567",
66
- "@teambit/ui-foundation.ui.main-dropdown": "0.0.470",
67
- "@teambit/ui-foundation.ui.menu": "0.0.470",
68
- "@teambit/ui-foundation.ui.react-router.slot-router": "0.0.472",
69
- "@teambit/toolbox.time.time-format": "0.0.467",
70
- "@teambit/component-id": "0.0.383",
71
- "@teambit/ui-foundation.ui.hooks.use-data-query": "0.0.471",
72
- "@teambit/deprecation": "0.0.567",
73
- "@teambit/ui-foundation.ui.constants.z-indexes": "0.0.471",
74
- "@teambit/ui-foundation.ui.buttons.collapser": "0.0.176",
75
- "@teambit/ui-foundation.ui.corner": "0.0.477",
76
- "@teambit/ui-foundation.ui.notifications.notification-context": "0.0.471",
77
- "@teambit/ui-foundation.ui.top-bar": "0.0.473",
67
+ "@teambit/graph": "0.0.571",
68
+ "@teambit/react-router": "0.0.571",
69
+ "@teambit/sidebar": "0.0.571",
70
+ "@teambit/ui-foundation.ui.main-dropdown": "0.0.472",
71
+ "@teambit/ui-foundation.ui.menu": "0.0.472",
72
+ "@teambit/ui-foundation.ui.react-router.slot-router": "0.0.474",
73
+ "@teambit/toolbox.time.time-format": "0.0.469",
74
+ "@teambit/component-id": "0.0.385",
75
+ "@teambit/ui-foundation.ui.hooks.use-data-query": "0.0.473",
76
+ "@teambit/deprecation": "0.0.571",
77
+ "@teambit/ui-foundation.ui.constants.z-indexes": "0.0.473",
78
+ "@teambit/ui-foundation.ui.buttons.collapser": "0.0.178",
79
+ "@teambit/ui-foundation.ui.corner": "0.0.479",
80
+ "@teambit/ui-foundation.ui.notifications.notification-context": "0.0.473",
81
+ "@teambit/ui-foundation.ui.top-bar": "0.0.475",
78
82
  "@teambit/design.ui.styles.ellipsis": "0.0.346",
79
83
  "@teambit/design.ui.styles.muted-italic": "0.0.35",
80
- "@teambit/ui-foundation.ui.full-loader": "0.0.470",
81
- "@teambit/ui-foundation.ui.side-bar": "0.0.476",
82
- "@teambit/ui-foundation.ui.tree.drawer": "0.0.470",
83
- "@teambit/explorer.ui.gallery.component-grid": "0.0.470",
84
- "@teambit/workspace.ui.empty-workspace": "0.0.472",
85
- "@teambit/workspace.ui.workspace-component-card": "0.0.474"
84
+ "@teambit/ui-foundation.ui.full-loader": "0.0.472",
85
+ "@teambit/ui-foundation.ui.side-bar": "0.0.478",
86
+ "@teambit/ui-foundation.ui.tree.drawer": "0.0.472",
87
+ "@teambit/explorer.ui.gallery.component-grid": "0.0.472",
88
+ "@teambit/workspace.ui.empty-workspace": "0.0.474",
89
+ "@teambit/workspace.ui.workspace-component-card": "0.0.476"
86
90
  },
87
91
  "devDependencies": {
88
92
  "@types/lodash.compact": "3.0.6",
@@ -102,7 +106,7 @@
102
106
  },
103
107
  "peerDependencies": {
104
108
  "@apollo/client": "^3.0.0",
105
- "@teambit/legacy": "1.0.179",
109
+ "@teambit/legacy": "1.0.181",
106
110
  "react-dom": "^16.8.0 || ^17.0.0",
107
111
  "react": "^16.8.0 || ^17.0.0"
108
112
  },
@@ -130,27 +134,12 @@
130
134
  "react": "-"
131
135
  },
132
136
  "peerDependencies": {
133
- "@teambit/legacy": "1.0.179",
137
+ "@teambit/legacy": "1.0.181",
134
138
  "react-dom": "^16.8.0 || ^17.0.0",
135
139
  "react": "^16.8.0 || ^17.0.0"
136
140
  }
137
141
  }
138
142
  },
139
- "files": [
140
- "dist",
141
- "!dist/tsconfig.tsbuildinfo",
142
- "**/*.md",
143
- "**/*.mdx",
144
- "**/*.js",
145
- "**/*.json",
146
- "**/*.sass",
147
- "**/*.scss",
148
- "**/*.less",
149
- "**/*.css",
150
- "**/*.css",
151
- "**/*.jpeg",
152
- "**/*.gif"
153
- ],
154
143
  "private": false,
155
144
  "engines": {
156
145
  "node": ">=12.22.0"
@@ -0,0 +1,29 @@
1
+ declare module '*.png' {
2
+ const value: any;
3
+ export = value;
4
+ }
5
+ declare module '*.svg' {
6
+ import type { FunctionComponent, SVGProps } from 'react';
7
+
8
+ export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
9
+ const src: string;
10
+ export default src;
11
+ }
12
+
13
+ // @TODO Gilad
14
+ declare module '*.jpg' {
15
+ const value: any;
16
+ export = value;
17
+ }
18
+ declare module '*.jpeg' {
19
+ const value: any;
20
+ export = value;
21
+ }
22
+ declare module '*.gif' {
23
+ const value: any;
24
+ export = value;
25
+ }
26
+ declare module '*.bmp' {
27
+ const value: any;
28
+ export = value;
29
+ }
@@ -0,0 +1,42 @@
1
+ declare module '*.module.css' {
2
+ const classes: { readonly [key: string]: string };
3
+ export default classes;
4
+ }
5
+ declare module '*.module.scss' {
6
+ const classes: { readonly [key: string]: string };
7
+ export default classes;
8
+ }
9
+ declare module '*.module.sass' {
10
+ const classes: { readonly [key: string]: string };
11
+ export default classes;
12
+ }
13
+
14
+ declare module '*.module.less' {
15
+ const classes: { readonly [key: string]: string };
16
+ export default classes;
17
+ }
18
+
19
+ declare module '*.less' {
20
+ const classes: { readonly [key: string]: string };
21
+ export default classes;
22
+ }
23
+
24
+ declare module '*.css' {
25
+ const classes: { readonly [key: string]: string };
26
+ export default classes;
27
+ }
28
+
29
+ declare module '*.sass' {
30
+ const classes: { readonly [key: string]: string };
31
+ export default classes;
32
+ }
33
+
34
+ declare module '*.scss' {
35
+ const classes: { readonly [key: string]: string };
36
+ export default classes;
37
+ }
38
+
39
+ declare module '*.mdx' {
40
+ const component: any;
41
+ export default component;
42
+ }
package/ui/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { Workspace } from './workspace';
@@ -0,0 +1,7 @@
1
+ export const defaultComponent = {
2
+ id: '',
3
+ server: {
4
+ url: '',
5
+ env: '',
6
+ },
7
+ };
@@ -0,0 +1 @@
1
+ export * from './workspace';
@@ -0,0 +1,193 @@
1
+ import { useEffect, useMemo } from 'react';
2
+ import { ComponentModel } from '@teambit/component';
3
+ import useLatest from '@react-hook/latest';
4
+ import { useDataQuery } from '@teambit/ui-foundation.ui.hooks.use-data-query';
5
+ import { gql } from '@apollo/client';
6
+ import { ComponentID, ComponentIdObj } from '@teambit/component-id';
7
+
8
+ import { Workspace } from './workspace-model';
9
+
10
+ type UseWorkspaceOptions = {
11
+ onComponentAdded?: (component: ComponentModel[]) => void;
12
+ onComponentUpdated?: (component: ComponentModel[]) => void;
13
+ onComponentRemoved?: (compId: ComponentID[]) => void;
14
+ };
15
+ type RawComponent = { id: ComponentIdObj };
16
+
17
+ const wcComponentFields = gql`
18
+ fragment wcComponentFields on Component {
19
+ id {
20
+ name
21
+ version
22
+ scope
23
+ }
24
+ compositions {
25
+ identifier
26
+ }
27
+ description
28
+ issuesCount
29
+ status {
30
+ isOutdated
31
+ isNew
32
+ isInScope
33
+ isStaged
34
+ modifyInfo {
35
+ hasModifiedFiles
36
+ hasModifiedDependencies
37
+ }
38
+ isDeleted
39
+ }
40
+ deprecation {
41
+ isDeprecate
42
+ }
43
+ server {
44
+ env
45
+ url
46
+ }
47
+ env {
48
+ id
49
+ icon
50
+ }
51
+ }
52
+ `;
53
+
54
+ const WORKSPACE = gql`
55
+ query workspace {
56
+ workspace {
57
+ name
58
+ path
59
+ icon
60
+ components {
61
+ ...wcComponentFields
62
+ }
63
+ }
64
+ }
65
+ ${wcComponentFields}
66
+ `;
67
+
68
+ const COMPONENT_SUBSCRIPTION_ADDED = gql`
69
+ subscription OnComponentAdded {
70
+ componentAdded {
71
+ component {
72
+ ...wcComponentFields
73
+ }
74
+ }
75
+ }
76
+ ${wcComponentFields}
77
+ `;
78
+
79
+ const COMPONENT_SUBSCRIPTION_CHANGED = gql`
80
+ subscription OnComponentChanged {
81
+ componentChanged {
82
+ component {
83
+ ...wcComponentFields
84
+ }
85
+ }
86
+ }
87
+ ${wcComponentFields}
88
+ `;
89
+
90
+ const COMPONENT_SUBSCRIPTION_REMOVED = gql`
91
+ subscription OnComponentRemoved {
92
+ componentRemoved {
93
+ componentIds {
94
+ name
95
+ version
96
+ scope
97
+ }
98
+ }
99
+ }
100
+ `;
101
+
102
+ export function useWorkspace(options: UseWorkspaceOptions = {}) {
103
+ const { data, subscribeToMore, ...rest } = useDataQuery(WORKSPACE);
104
+ const optionsRef = useLatest(options);
105
+
106
+ useEffect(() => {
107
+ const unSubCompAddition = subscribeToMore({
108
+ document: COMPONENT_SUBSCRIPTION_ADDED,
109
+ updateQuery: (prev, { subscriptionData }) => {
110
+ const update = subscriptionData.data;
111
+ const addedComponent = update?.componentAdded?.component;
112
+ if (!addedComponent) return prev;
113
+
114
+ const componentExists = prev.workspace.components.find((component: any) =>
115
+ ComponentID.isEqualObj(component.id, addedComponent.id, { ignoreVersion: true })
116
+ );
117
+ if (componentExists) return prev;
118
+
119
+ // side effect - trigger observers
120
+ setTimeout(() => optionsRef.current.onComponentAdded?.([ComponentModel.from(addedComponent)]));
121
+
122
+ return {
123
+ ...prev,
124
+ workspace: {
125
+ ...prev.workspace,
126
+ components: [...prev.workspace.components, addedComponent],
127
+ },
128
+ };
129
+ },
130
+ });
131
+
132
+ const unSubCompChange = subscribeToMore({
133
+ document: COMPONENT_SUBSCRIPTION_CHANGED,
134
+ updateQuery: (prev, { subscriptionData }) => {
135
+ const update = subscriptionData.data;
136
+ if (!update) return prev;
137
+
138
+ const updatedComponent = update.componentChanged.component;
139
+ // side effect - trigger observers
140
+ setTimeout(() => optionsRef.current.onComponentUpdated?.([ComponentModel.from(updatedComponent)]));
141
+
142
+ return {
143
+ ...prev,
144
+ workspace: {
145
+ ...prev.workspace,
146
+ components: prev.workspace.components.map((component) =>
147
+ component.id.name === updatedComponent.id.name ? updatedComponent : component
148
+ ),
149
+ },
150
+ };
151
+ },
152
+ });
153
+
154
+ const unSubCompRemoved = subscribeToMore({
155
+ document: COMPONENT_SUBSCRIPTION_REMOVED,
156
+ updateQuery: (prev, { subscriptionData }) => {
157
+ const idsToRemove: ComponentIdObj[] | undefined = subscriptionData.data?.componentRemoved?.componentIds;
158
+ if (!idsToRemove || idsToRemove.length === 0) return prev;
159
+
160
+ // side effect - trigger observers
161
+ setTimeout(() => optionsRef.current.onComponentRemoved?.(idsToRemove.map((id) => ComponentID.fromObject(id))));
162
+
163
+ return {
164
+ ...prev,
165
+ workspace: {
166
+ ...prev.workspace,
167
+ components: prev.workspace.components.filter((component: RawComponent) =>
168
+ idsToRemove.every((id) => !ComponentID.isEqualObj(id, component.id))
169
+ ),
170
+ },
171
+ };
172
+ },
173
+ });
174
+
175
+ // TODO - sub to component removal
176
+
177
+ return () => {
178
+ unSubCompAddition();
179
+ unSubCompChange();
180
+ unSubCompRemoved();
181
+ };
182
+ }, [optionsRef]);
183
+
184
+ const workspace = useMemo(() => {
185
+ return data?.workspace ? Workspace.from(data?.workspace) : undefined;
186
+ }, [data?.workspace]);
187
+
188
+ return {
189
+ workspace,
190
+ subscribeToMore,
191
+ ...rest,
192
+ };
193
+ }
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+
3
+ import { Workspace as WorkspaceModel } from './workspace-model';
4
+
5
+ export const WorkspaceContext: React.Context<WorkspaceModel> = createContext<WorkspaceModel>(WorkspaceModel.empty());
@@ -0,0 +1,66 @@
1
+ // import { ComponentMeta } from '@teambit/component';
2
+ import { ComponentID, ComponentModel, ComponentModelProps } from '@teambit/component';
3
+ import { DeprecationInfo } from '@teambit/deprecation';
4
+ import { Descriptor } from '@teambit/envs';
5
+
6
+ import { ComponentStatus } from '../../workspace-component/component-status';
7
+
8
+ export type WorkspaceModelComponent = {
9
+ id: ComponentID;
10
+ status: ComponentStatus;
11
+ deprecation: DeprecationInfo;
12
+ env: Descriptor;
13
+ };
14
+
15
+ export type WorkspaceProps = {
16
+ name: string;
17
+ path: string;
18
+ components: ComponentModelProps[];
19
+ icon: string;
20
+ };
21
+
22
+ export class Workspace {
23
+ constructor(
24
+ /**
25
+ * name of the workspace.
26
+ */
27
+ readonly name: string,
28
+
29
+ /**
30
+ * absolute path of the workspace.
31
+ */
32
+ readonly path: string,
33
+
34
+ /**
35
+ * icon of the workspace.
36
+ */
37
+ readonly icon: string,
38
+
39
+ /**
40
+ * components container in the workspace.
41
+ */
42
+ readonly components: ComponentModel[]
43
+ ) {}
44
+
45
+ /**
46
+ * return a component from the workspace.
47
+ */
48
+ getComponent(id: ComponentID) {
49
+ return this.components.find((component) => component.id.fullName === id.fullName);
50
+ }
51
+
52
+ static from({ name, path, components, icon }: WorkspaceProps) {
53
+ return new Workspace(
54
+ name,
55
+ path,
56
+ icon,
57
+ components.map((value) => {
58
+ return ComponentModel.from(value);
59
+ })
60
+ );
61
+ }
62
+
63
+ static empty() {
64
+ return new Workspace('', '', '', []);
65
+ }
66
+ }
@@ -0,0 +1 @@
1
+ export { WorkspaceOverview } from './workspace-overview';
@@ -0,0 +1,21 @@
1
+ import React, { useContext } from 'react';
2
+ import { ComponentGrid } from '@teambit/explorer.ui.gallery.component-grid';
3
+ import { EmptyWorkspace } from '@teambit/workspace.ui.empty-workspace';
4
+ import { WorkspaceComponentCard } from '@teambit/workspace.ui.workspace-component-card';
5
+ import { WorkspaceContext } from '../workspace-context';
6
+ import styles from './workspace-overview.module.scss';
7
+
8
+ export function WorkspaceOverview() {
9
+ const workspace = useContext(WorkspaceContext);
10
+ const { components } = workspace;
11
+ if (!components || components.length === 0) return <EmptyWorkspace name={workspace.name} />;
12
+ return (
13
+ <div className={styles.container}>
14
+ <ComponentGrid>
15
+ {components.map((component, index) => {
16
+ return <WorkspaceComponentCard key={index} component={component} />;
17
+ })}
18
+ </ComponentGrid>
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,23 @@
1
+ import React, { ReactNode } from 'react';
2
+
3
+ import { WorkspaceContext } from './workspace-context';
4
+ import { Workspace } from './workspace-model';
5
+
6
+ export type WorkspaceProviderProps = {
7
+ /**
8
+ * workspace model.
9
+ */
10
+ workspace: Workspace;
11
+
12
+ /**
13
+ * react children.
14
+ */
15
+ children: ReactNode;
16
+ };
17
+
18
+ /**
19
+ * context provider of the workspace
20
+ */
21
+ export function WorkspaceProvider({ workspace, children }: WorkspaceProviderProps) {
22
+ return <WorkspaceContext.Provider value={workspace}>{children}</WorkspaceContext.Provider>;
23
+ }
@@ -0,0 +1,99 @@
1
+ import 'reset-css';
2
+ import pluralize from 'pluralize';
3
+ import React, { useReducer, useMemo } from 'react';
4
+ import { Route } from 'react-router-dom';
5
+ import type { ComponentModel } from '@teambit/component';
6
+ import type { ComponentID } from '@teambit/component-id';
7
+ import { useNotifications } from '@teambit/ui-foundation.ui.notifications.notification-context';
8
+ import { RouteSlot, SlotRouter } from '@teambit/ui-foundation.ui.react-router.slot-router';
9
+ import { Corner } from '@teambit/ui-foundation.ui.corner';
10
+ import { Collapser } from '@teambit/ui-foundation.ui.buttons.collapser';
11
+ import { SplitPane, Pane, Layout } from '@teambit/base-ui.surfaces.split-pane.split-pane';
12
+ import { HoverSplitter } from '@teambit/base-ui.surfaces.split-pane.hover-splitter';
13
+ import { TopBar } from '@teambit/ui-foundation.ui.top-bar';
14
+
15
+ import { useWorkspace } from './use-workspace';
16
+ import { WorkspaceOverview } from './workspace-overview';
17
+ import { WorkspaceProvider } from './workspace-provider';
18
+ import styles from './workspace.module.scss';
19
+ import WorkspaceUI from '../../workspace.ui.runtime';
20
+
21
+ export type WorkspaceProps = {
22
+ routeSlot: RouteSlot;
23
+ menuSlot: RouteSlot;
24
+ sidebar: JSX.Element;
25
+ workspaceUI: WorkspaceUI;
26
+ onSidebarTogglerChange: (callback: () => void) => void;
27
+ };
28
+
29
+ /**
30
+ * main workspace component.
31
+ */
32
+ export function Workspace({ routeSlot, menuSlot, sidebar, workspaceUI, onSidebarTogglerChange }: WorkspaceProps) {
33
+ const reactions = useComponentNotifications();
34
+ const { workspace } = useWorkspace(reactions);
35
+
36
+ const [isSidebarOpen, handleSidebarToggle] = useReducer((x) => !x, true);
37
+ const sidebarOpenness = isSidebarOpen ? Layout.row : Layout.right;
38
+
39
+ onSidebarTogglerChange(handleSidebarToggle);
40
+
41
+ if (!workspace) {
42
+ return <div className={styles.emptyContainer}></div>;
43
+ }
44
+
45
+ workspaceUI.setComponents(workspace.components);
46
+
47
+ return (
48
+ <WorkspaceProvider workspace={workspace}>
49
+ <div className={styles.workspaceWrapper}>
50
+ <TopBar
51
+ className={styles.topbar}
52
+ Corner={() => <Corner name={workspace.name} icon={workspace.icon} />}
53
+ menu={menuSlot}
54
+ />
55
+
56
+ <SplitPane className={styles.main} size={264} layout={sidebarOpenness}>
57
+ <Pane className={styles.sidebar}>{sidebar}</Pane>
58
+ <HoverSplitter className={styles.splitter}>
59
+ <Collapser
60
+ isOpen={isSidebarOpen}
61
+ onMouseDown={(e) => e.stopPropagation()} // avoid split-pane drag
62
+ onClick={handleSidebarToggle}
63
+ tooltipContent={`${isSidebarOpen ? 'Hide' : 'Show'} side panel`}
64
+ />
65
+ </HoverSplitter>
66
+ <Pane>
67
+ <SlotRouter slot={routeSlot} />
68
+ <Route exact path="/">
69
+ <WorkspaceOverview />
70
+ </Route>
71
+ </Pane>
72
+ </SplitPane>
73
+ </div>
74
+ </WorkspaceProvider>
75
+ );
76
+ }
77
+ function useComponentNotifications() {
78
+ const notifications = useNotifications();
79
+
80
+ // memo not really needed, but for peace of mind
81
+ return useMemo(
82
+ () => ({
83
+ onComponentAdded: (comps: ComponentModel[]) => {
84
+ const notificationId = notifications.log(
85
+ `added ${pluralize('component', comps.length)}: ${comps.map((comp) => comp.id.toString()).join(', ')}`
86
+ );
87
+ setTimeout(() => notifications.dismiss(notificationId), 12 * 1000);
88
+ },
89
+
90
+ onComponentRemoved: (ids: ComponentID[]) => {
91
+ const notificationId = notifications.log(
92
+ `removed ${pluralize('component', ids.length)} ${ids.map((id) => id.toString()).join(', ')}`
93
+ );
94
+ setTimeout(() => notifications.dismiss(notificationId), 12 * 1000);
95
+ },
96
+ }),
97
+ [notifications]
98
+ );
99
+ }
@@ -0,0 +1 @@
1
+ export { WorkspaceComponentsDrawer } from './workspace-components.drawer';