@teambit/component 0.0.566 → 0.0.570

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 (52) hide show
  1. package/aspect.section.tsx +16 -0
  2. package/component-map/component-map.ts +106 -0
  3. package/component-map/index.ts +1 -0
  4. package/component.ui.runtime.tsx +216 -0
  5. package/dependencies/dependencies.ts +74 -0
  6. package/dependencies/index.ts +1 -0
  7. package/exceptions/could-not-find-latest.ts +8 -0
  8. package/exceptions/host-not-found.ts +14 -0
  9. package/exceptions/index.ts +4 -0
  10. package/exceptions/nothing-to-snap.ts +1 -0
  11. package/host/component-host-model.ts +9 -0
  12. package/host/index.ts +2 -0
  13. package/host/use-component-host.ts +39 -0
  14. package/package-tar/teambit-component-0.0.570.tgz +0 -0
  15. package/package.json +34 -49
  16. package/section/index.ts +1 -0
  17. package/section/section.tsx +8 -0
  18. package/show/extensions.fragment.ts +23 -0
  19. package/show/files.fragment.ts +24 -0
  20. package/show/id.fragment.ts +20 -0
  21. package/show/index.ts +8 -0
  22. package/show/main-file.fragment.ts +13 -0
  23. package/show/name.fragment.ts +13 -0
  24. package/show/scope.fragment.ts +15 -0
  25. package/show/show-fragment.ts +44 -0
  26. package/show/show.cmd.ts +85 -0
  27. package/snap/author.ts +19 -0
  28. package/snap/index.ts +2 -0
  29. package/snap/snap.ts +63 -0
  30. package/tag/index.ts +1 -0
  31. package/tag/tag.ts +37 -0
  32. package/types/asset.d.ts +29 -0
  33. package/types/style.d.ts +42 -0
  34. package/ui/aspect-page/aspect-page.tsx +64 -0
  35. package/ui/aspect-page/index.ts +1 -0
  36. package/ui/component-error/component-error.tsx +22 -0
  37. package/ui/component-error/index.ts +1 -0
  38. package/ui/component-model/component-model.ts +169 -0
  39. package/ui/component-model/index.ts +1 -0
  40. package/ui/component.tsx +48 -0
  41. package/ui/context/component-context.ts +5 -0
  42. package/ui/context/component-provider.tsx +20 -0
  43. package/ui/context/index.ts +2 -0
  44. package/ui/index.ts +3 -0
  45. package/ui/menu/index.ts +2 -0
  46. package/ui/menu/menu-nav.tsx +37 -0
  47. package/ui/menu/menu.tsx +94 -0
  48. package/ui/menu/nav-plugin.tsx +9 -0
  49. package/ui/top-bar-nav/index.ts +1 -0
  50. package/ui/top-bar-nav/top-bar-nav.tsx +26 -0
  51. package/ui/use-component-query.ts +195 -0
  52. package/ui/use-component.tsx +34 -0
@@ -0,0 +1,24 @@
1
+ import { ShowFragment } from './show-fragment';
2
+ import { Component } from '../component';
3
+
4
+ export class FilesFragment implements ShowFragment {
5
+ async renderRow(component: Component) {
6
+ return {
7
+ title: 'files',
8
+ content: this.getRelativePaths(component).join('\n'),
9
+ };
10
+ }
11
+
12
+ async json(component: Component) {
13
+ return {
14
+ title: 'files',
15
+ json: this.getRelativePaths(component),
16
+ };
17
+ }
18
+
19
+ private getRelativePaths(component: Component) {
20
+ return component.state.filesystem.files.map((file) => file.relative);
21
+ }
22
+
23
+ weight = 4;
24
+ }
@@ -0,0 +1,20 @@
1
+ import { ShowFragment } from './show-fragment';
2
+ import { Component } from '../component';
3
+
4
+ export class IDFragment implements ShowFragment {
5
+ async renderRow(component: Component) {
6
+ return {
7
+ title: 'id',
8
+ content: component.id.toString(),
9
+ };
10
+ }
11
+
12
+ async json(component: Component) {
13
+ return {
14
+ title: 'id',
15
+ json: component.id.toString(),
16
+ };
17
+ }
18
+
19
+ weight = 0;
20
+ }
package/show/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export { ShowFragment, ShowRow } from './show-fragment';
2
+ export { ShowCmd } from './show.cmd';
3
+ export { MainFileFragment } from './main-file.fragment';
4
+ export { NameFragment } from './name.fragment';
5
+ export { IDFragment } from './id.fragment';
6
+ export { ScopeFragment } from './scope.fragment';
7
+ export { FilesFragment } from './files.fragment';
8
+ export { ExtensionsFragment } from './extensions.fragment';
@@ -0,0 +1,13 @@
1
+ import { ShowFragment } from './show-fragment';
2
+ import { Component } from '../component';
3
+
4
+ export class MainFileFragment implements ShowFragment {
5
+ async renderRow(component: Component) {
6
+ return {
7
+ title: 'main file',
8
+ content: component.state._consumer.mainFile,
9
+ };
10
+ }
11
+
12
+ weight = 4;
13
+ }
@@ -0,0 +1,13 @@
1
+ import { ShowFragment } from './show-fragment';
2
+ import { Component } from '../component';
3
+
4
+ export class NameFragment implements ShowFragment {
5
+ async renderRow(component: Component) {
6
+ return {
7
+ title: 'name',
8
+ content: component.id.fullName,
9
+ };
10
+ }
11
+
12
+ weight = 2;
13
+ }
@@ -0,0 +1,15 @@
1
+ import { ShowFragment } from './show-fragment';
2
+ import { Component } from '../component';
3
+
4
+ export class ScopeFragment implements ShowFragment {
5
+ async renderRow(component: Component) {
6
+ return {
7
+ title: 'scope',
8
+ content: component.id.scope || '',
9
+ };
10
+ }
11
+
12
+ getRow() {}
13
+
14
+ weight = 1;
15
+ }
@@ -0,0 +1,44 @@
1
+ import { Component } from '../component';
2
+
3
+ export interface ShowFragment {
4
+ /**
5
+ * render a row into the `show` CLI.
6
+ */
7
+ renderRow(component: Component): Promise<ShowRow>;
8
+
9
+ /**
10
+ * return a json output.
11
+ */
12
+ json?(component: Component): Promise<JSONRow>;
13
+
14
+ /**
15
+ * weight is used to determine the position of the fragment
16
+ * within the `show` table.
17
+ */
18
+ weight?: number;
19
+ }
20
+
21
+ export interface JSONRow {
22
+ /**
23
+ * name of the field.
24
+ */
25
+ title: string;
26
+
27
+ /**
28
+ * json content.
29
+ * TODO: change this from any to a more structured type (e.g. Serializable).
30
+ */
31
+ json: any;
32
+ }
33
+
34
+ export interface ShowRow {
35
+ /**
36
+ * title of the fragment
37
+ */
38
+ title: string;
39
+
40
+ /**
41
+ * content to render within the fragment.
42
+ */
43
+ content: string;
44
+ }
@@ -0,0 +1,85 @@
1
+ import { Command, CommandOptions } from '@teambit/cli';
2
+ // import { Logger } from '@teambit/logger';
3
+ // import chalk from 'chalk';
4
+ import { CLITable } from '@teambit/cli-table';
5
+ import { MissingBitMapComponent } from '@teambit/legacy/dist/consumer/bit-map/exceptions';
6
+ import { BitId } from '@teambit/legacy-bit-id';
7
+ import LegacyShow from '@teambit/legacy/dist/cli/commands/public-cmds/show-cmd';
8
+ import { ComponentMain } from '../component.main.runtime';
9
+
10
+ export class ShowCmd implements Command {
11
+ name = 'show <id>';
12
+ description = 'show a component';
13
+ alias = '';
14
+ group = 'info';
15
+ options = [
16
+ ['j', 'json', 'return the component data in json format'],
17
+ ['l', 'legacy', 'use the legacy bit show.'],
18
+ ['r', 'remote', 'show a remote component'],
19
+ [
20
+ 'c',
21
+ 'compare',
22
+ 'compare current file system component to latest tagged component [default=latest]. only works in legacy.',
23
+ ],
24
+ ] as CommandOptions;
25
+
26
+ constructor(private component: ComponentMain) {}
27
+
28
+ private async getComponent(idStr: string, remote: boolean) {
29
+ if (remote) {
30
+ const bitId: BitId = BitId.parse(idStr, true); // user used --remote so we know it has a scope
31
+ const host = this.component.getHost('teambit.scope/scope');
32
+ const id = await host.resolveComponentId(bitId);
33
+ if (!host.getRemoteComponent) {
34
+ throw new Error('Component Host does not implement getRemoteComponent()');
35
+ }
36
+ const component = await host.getRemoteComponent(id);
37
+ return component;
38
+ }
39
+ const host = this.component.getHost();
40
+ const id = await host.resolveComponentId(idStr);
41
+ const component = await host.get(id);
42
+ if (!component) throw new MissingBitMapComponent(idStr);
43
+ return component;
44
+ }
45
+
46
+ async useLegacy(id: string, json = false, remote = false, compare = false) {
47
+ const legacyShow = new LegacyShow();
48
+ const showData = await legacyShow.action([id], {
49
+ json,
50
+ versions: undefined,
51
+ remote,
52
+ compare,
53
+ });
54
+
55
+ return legacyShow.report(showData);
56
+ }
57
+
58
+ async report([idStr]: [string], { legacy, remote, compare }: { legacy: boolean; remote: boolean; compare: boolean }) {
59
+ if (legacy) return this.useLegacy(idStr, false, remote, compare);
60
+ const component = await this.getComponent(idStr, remote);
61
+ const fragments = this.component.getShowFragments();
62
+ const rows = await Promise.all(
63
+ fragments.map(async (fragment) => {
64
+ const row = await fragment.renderRow(component);
65
+ return [row.title, row.content];
66
+ })
67
+ );
68
+
69
+ const table = new CLITable([], rows);
70
+ return table.render();
71
+ }
72
+
73
+ async json([idStr]: [string], { remote, legacy }: { remote: boolean; legacy: boolean }) {
74
+ if (legacy) return JSON.parse(await this.useLegacy(idStr, true, remote));
75
+ const component = await this.getComponent(idStr, remote);
76
+ const fragments = this.component.getShowFragments();
77
+ const rows = await Promise.all(
78
+ fragments.map(async (fragment) => {
79
+ return fragment.json ? fragment.json(component) : undefined;
80
+ })
81
+ );
82
+
83
+ return rows.filter((row) => !!row);
84
+ }
85
+ }
package/snap/author.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * author type.
3
+ */
4
+ export type Author = {
5
+ /**
6
+ * author full name (for example: "Ran Mizrahi")
7
+ */
8
+ displayName: string;
9
+ /**
10
+ * author username (for example: "ranm8")
11
+ */
12
+ name?: string; // added this to support the usual structure of an author
13
+ // TODO - @ran, is this ok with you?
14
+
15
+ /**
16
+ * author email in a proper format (e.g. "ran@bit.dev")
17
+ */
18
+ email: string;
19
+ };
package/snap/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Author } from './author';
2
+ export { Snap, SnapProps } from './snap';
package/snap/snap.ts ADDED
@@ -0,0 +1,63 @@
1
+ import { Author } from './author';
2
+
3
+ export type SnapProps = {
4
+ hash: string;
5
+ timestamp: string;
6
+ parents: string[];
7
+ author: Author;
8
+ message: string;
9
+ };
10
+
11
+ /**
12
+ * `Snap` represents a sealed state of the component in the working tree.
13
+ */
14
+ export class Snap {
15
+ constructor(
16
+ /**
17
+ * hash of the snap.
18
+ */
19
+ readonly hash: string,
20
+
21
+ /**
22
+ * date time of the snap.
23
+ */
24
+ readonly timestamp: Date,
25
+
26
+ /**
27
+ * parent snap
28
+ */
29
+ readonly parents: string[],
30
+
31
+ /**
32
+ * author of the component `Snap`.
33
+ */
34
+ readonly author: Author,
35
+
36
+ /**
37
+ * message added by the `Snap` author.
38
+ */
39
+ readonly message: string
40
+ ) {}
41
+
42
+ static fromObject(snapObject: SnapProps) {
43
+ const parents = snapObject.parents || [];
44
+
45
+ return new Snap(
46
+ snapObject.hash,
47
+ new Date(parseInt(snapObject.timestamp)),
48
+ parents,
49
+ snapObject.author,
50
+ snapObject.message
51
+ );
52
+ }
53
+
54
+ toObject(): SnapProps {
55
+ return {
56
+ timestamp: this.timestamp.getTime().toString(),
57
+ hash: this.hash,
58
+ author: this.author,
59
+ message: this.message,
60
+ parents: this.parents,
61
+ };
62
+ }
63
+ }
package/tag/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { Tag } from './tag';
package/tag/tag.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { SemVer } from 'semver';
2
+
3
+ export type TagProps = {
4
+ hash: string;
5
+ version: string;
6
+ };
7
+
8
+ /**
9
+ * `Tag` provides a sematic reference to a specific state `Snap` in the working tree.
10
+ */
11
+ export class Tag {
12
+ constructor(
13
+ /**
14
+ * tag hash, can be used to load it by component-factory.getSnap
15
+ */
16
+ readonly hash: string,
17
+
18
+ /**
19
+ * sematic version of the snap.
20
+ */
21
+ readonly version: SemVer
22
+ ) {}
23
+
24
+ /**
25
+ * create a plain tag object.
26
+ */
27
+ toObject(): TagProps {
28
+ return {
29
+ hash: this.hash,
30
+ version: this.version.raw,
31
+ };
32
+ }
33
+
34
+ static fromObject(tag: TagProps) {
35
+ return new Tag(tag.hash, new SemVer(tag.version));
36
+ }
37
+ }
@@ -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
+ }
@@ -0,0 +1,64 @@
1
+ import { AspectBox } from '@teambit/harmony.ui.aspect-box';
2
+ import { ComponentContext } from '@teambit/component';
3
+ import React, { useContext } from 'react';
4
+ import { useDataQuery } from '@teambit/ui-foundation.ui.hooks.use-data-query';
5
+ import { gql } from '@apollo/client';
6
+ import { EmptyBox } from '@teambit/design.ui.empty-box';
7
+ import { H1 } from '@teambit/documenter.ui.heading';
8
+ import { Separator } from '@teambit/documenter.ui.separator';
9
+ import styles from './aspect-page.module.scss';
10
+
11
+ const GET_COMPONENT = gql`
12
+ query($id: String!) {
13
+ getHost {
14
+ get(id: $id) {
15
+ aspects {
16
+ id
17
+ config
18
+ data
19
+ icon
20
+ }
21
+ }
22
+ }
23
+ }
24
+ `;
25
+
26
+ export function AspectPage() {
27
+ const component = useContext(ComponentContext);
28
+ const { data } = useDataQuery(GET_COMPONENT, {
29
+ variables: { id: component.id._legacy.name },
30
+ });
31
+ const aspectList = data?.getHost?.get?.aspects;
32
+
33
+ if (aspectList && aspectList.length === 0) {
34
+ return (
35
+ <EmptyBox
36
+ title="This component is new and doesn’t have any aspects."
37
+ linkText="Learn more about component aspects"
38
+ link="https://harmony-docs.bit.dev/aspects/aspects-overview"
39
+ />
40
+ );
41
+ }
42
+
43
+ return (
44
+ <div className={styles.aspectPage}>
45
+ <div>
46
+ <H1 className={styles.title}>Configuration</H1>
47
+ <Separator className={styles.separator} />
48
+ {aspectList &&
49
+ aspectList.map((aspect, index) => {
50
+ return (
51
+ <AspectBox
52
+ key={index}
53
+ className={styles.aspectBox}
54
+ name={aspect.id}
55
+ icon={aspect.icon}
56
+ config={aspect.config}
57
+ data={aspect.data}
58
+ />
59
+ );
60
+ })}
61
+ </div>
62
+ </div>
63
+ );
64
+ }
@@ -0,0 +1 @@
1
+ export { AspectPage } from './aspect-page';
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import { NotFoundPage } from '@teambit/design.ui.pages.not-found';
3
+ import { ServerErrorPage } from '@teambit/design.ui.pages.server-error';
4
+
5
+ export class ComponentError {
6
+ constructor(
7
+ /**
8
+ * http status code of error
9
+ */
10
+ public readonly code: number,
11
+
12
+ /**
13
+ * error message of the error
14
+ */
15
+ public readonly message?: string
16
+ ) {}
17
+
18
+ renderError() {
19
+ if (this.code === 404) return <NotFoundPage />;
20
+ return <ServerErrorPage />;
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ export { ComponentError } from './component-error';
@@ -0,0 +1,169 @@
1
+ import { Composition, CompositionProps } from '@teambit/compositions';
2
+ import { DeprecationInfo } from '@teambit/deprecation';
3
+ import { Descriptor } from '@teambit/envs';
4
+ import { ComponentID, ComponentIdObj } from '@teambit/component-id';
5
+
6
+ import { Tag } from '../../tag';
7
+ import { TagMap } from '../../tag-map';
8
+ import { TagProps } from '../../tag/tag';
9
+ // import { Snap } from '../../snap';
10
+
11
+ // ADDING MORE PROPERTIES HERE IS NOT ALLOWED!!! IF YOU NEED DATA PLEASE ADD A NEW
12
+ // HOOK FROM YOUR ASPECT!!!
13
+ // TODO: remove all properties from here to their rightful place in their aspects.
14
+ export type ComponentModelProps = {
15
+ id: ComponentIdObj;
16
+ description: string;
17
+ buildStatus?: string;
18
+ server?: ComponentServer;
19
+ displayName: string;
20
+ packageName: string; // pkg aspect
21
+ elementsUrl?: string; // pkg aspect
22
+ compositions?: CompositionProps[];
23
+ tags?: TagProps[];
24
+ issuesCount?: number; // component/issues aspect
25
+ status?: any; // workspace aspect.
26
+ deprecation?: DeprecationInfo; // deprecation aspect
27
+ env?: Descriptor; // env aspect.
28
+ labels?: string[];
29
+ host?: string;
30
+ };
31
+
32
+ export type ComponentServer = {
33
+ env: string;
34
+ url: string;
35
+ };
36
+
37
+ export class ComponentModel {
38
+ constructor(
39
+ /**
40
+ * id of the component
41
+ */
42
+ readonly id: ComponentID,
43
+
44
+ /**
45
+ * display name of the component.
46
+ */
47
+ readonly displayName: string,
48
+
49
+ /**
50
+ * package name of the component.
51
+ */
52
+ readonly packageName: string,
53
+
54
+ /**
55
+ * the component server.
56
+ */
57
+ readonly server: ComponentServer | undefined,
58
+
59
+ /**
60
+ * array of compositions
61
+ */
62
+ readonly compositions: Composition[],
63
+
64
+ /**
65
+ * tags of the component.
66
+ */
67
+ readonly tags: TagMap,
68
+
69
+ /**
70
+ * component build status
71
+ */
72
+ readonly buildStatus?: string,
73
+
74
+ /**
75
+ * issues of component.
76
+ */
77
+ readonly issuesCount?: number,
78
+ /**
79
+ * elements url
80
+ */
81
+ readonly elementsUrl?: string,
82
+ /**
83
+ * status of component.
84
+ */
85
+ readonly status?: any,
86
+
87
+ /**
88
+ * deprecation info of the component.
89
+ */
90
+ readonly deprecation?: DeprecationInfo,
91
+
92
+ /**
93
+ * env descriptor.
94
+ */
95
+ readonly environment?: Descriptor,
96
+
97
+ /**
98
+ * description of the component.
99
+ */
100
+
101
+ readonly description = '',
102
+
103
+ readonly labels: string[] = [],
104
+
105
+ /**
106
+ * host of the component
107
+ */
108
+ readonly host?: string
109
+ ) {}
110
+
111
+ get version() {
112
+ if (!this.id.version) return 'new';
113
+ return this.id.version;
114
+ }
115
+
116
+ /**
117
+ * create an instance of a component from a plain object.
118
+ */
119
+ static from({
120
+ id,
121
+ server,
122
+ displayName,
123
+ compositions = [],
124
+ packageName,
125
+ elementsUrl,
126
+ tags = [],
127
+ deprecation,
128
+ buildStatus,
129
+ env,
130
+ status,
131
+ issuesCount,
132
+ description,
133
+ labels,
134
+ host,
135
+ }: ComponentModelProps) {
136
+ return new ComponentModel(
137
+ ComponentID.fromObject(id),
138
+ displayName,
139
+ packageName,
140
+ server,
141
+ Composition.fromArray(compositions),
142
+ TagMap.fromArray(tags.map((tag) => Tag.fromObject(tag))),
143
+ buildStatus,
144
+ issuesCount,
145
+ elementsUrl,
146
+ status,
147
+ deprecation,
148
+ env,
149
+ description,
150
+ labels,
151
+ host
152
+ );
153
+ }
154
+
155
+ static fromArray(componentsProps: ComponentModelProps[]) {
156
+ return componentsProps.map((rawComponent) => ComponentModel.from(rawComponent));
157
+ }
158
+
159
+ static empty() {
160
+ return new ComponentModel(
161
+ ComponentID.fromObject({ name: 'root', scope: 'temp' }),
162
+ '',
163
+ '',
164
+ { env: '', url: '' },
165
+ [],
166
+ TagMap.empty()
167
+ );
168
+ }
169
+ }
@@ -0,0 +1 @@
1
+ export { ComponentModel, ComponentModelProps } from './component-model';