@teambit/component-compare 1.0.1080 → 1.0.1082
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.
- package/component-compare-page.module.scss +124 -0
- package/component-compare-page.tsx +509 -0
- package/component-compare.ui.runtime.tsx +98 -16
- package/dist/compare-component-pairs.d.ts +20 -0
- package/dist/compare-component-pairs.js +36 -0
- package/dist/compare-component-pairs.js.map +1 -0
- package/dist/compare-component-pairs.spec.d.ts +1 -0
- package/dist/compare-component-pairs.spec.js +94 -0
- package/dist/compare-component-pairs.spec.js.map +1 -0
- package/dist/component-compare-page.d.ts +16 -0
- package/dist/component-compare-page.js +504 -0
- package/dist/component-compare-page.js.map +1 -0
- package/dist/component-compare-page.module.scss +124 -0
- package/dist/component-compare.graphql.js +34 -0
- package/dist/component-compare.graphql.js.map +1 -1
- package/dist/component-compare.main.runtime.d.ts +64 -4
- package/dist/component-compare.main.runtime.js +187 -6
- package/dist/component-compare.main.runtime.js.map +1 -1
- package/dist/component-compare.ui.runtime.d.ts +43 -3
- package/dist/component-compare.ui.runtime.js +83 -21
- package/dist/component-compare.ui.runtime.js.map +1 -1
- package/dist/diff-cmd.d.ts +3 -3
- package/dist/{preview-1785267101230.js → preview-1785362864561.js} +2 -2
- package/package.json +35 -21
|
@@ -5,7 +5,6 @@ import type { Harmony, SlotRegistry } from '@teambit/harmony';
|
|
|
5
5
|
import { Slot } from '@teambit/harmony';
|
|
6
6
|
import type { ComponentUI } from '@teambit/component';
|
|
7
7
|
import { ComponentAspect } from '@teambit/component';
|
|
8
|
-
import { ComponentCompare } from '@teambit/component.ui.component-compare.component-compare';
|
|
9
8
|
import { UIRuntime } from '@teambit/ui';
|
|
10
9
|
import type { RouteSlot } from '@teambit/ui-foundation.ui.react-router.slot-router';
|
|
11
10
|
import type {
|
|
@@ -14,41 +13,50 @@ import type {
|
|
|
14
13
|
} from '@teambit/component.ui.component-compare.models.component-compare-props';
|
|
15
14
|
import { ComponentCompareChangelog } from '@teambit/component.ui.component-compare.changelog';
|
|
16
15
|
import { ComponentCompareAspects } from '@teambit/component.ui.component-compare.compare-aspects.compare-aspects';
|
|
16
|
+
import type { ApiDiffInsight } from '@teambit/semantics.ui.api-diff-view';
|
|
17
17
|
import { AspectsCompareSection } from './component-compare-aspects.section';
|
|
18
18
|
import { ComponentCompareAspect } from './component-compare.aspect';
|
|
19
19
|
import { ComponentCompareSection } from './component-compare.section';
|
|
20
20
|
import { CompareChangelogSection } from './component-compare-changelog.section';
|
|
21
|
+
import { ComponentComparePage } from './component-compare-page';
|
|
21
22
|
|
|
22
23
|
export type ComponentCompareNav = Array<TabItem>;
|
|
23
24
|
export type ComponentCompareNavSlot = SlotRegistry<ComponentCompareNav>;
|
|
25
|
+
|
|
26
|
+
export type ComponentCompareTabSlot = SlotRegistry<TabItem | TabItem[]>;
|
|
27
|
+
|
|
28
|
+
export type ApiDiffInsightSlot = SlotRegistry<ApiDiffInsight | ApiDiffInsight[]>;
|
|
29
|
+
|
|
24
30
|
export class ComponentCompareUI {
|
|
25
31
|
constructor(
|
|
26
32
|
private host: string,
|
|
27
33
|
private navSlot: ComponentCompareNavSlot,
|
|
28
34
|
private routeSlot: RouteSlot,
|
|
35
|
+
private compareTabSlot: ComponentCompareTabSlot,
|
|
36
|
+
private apiDiffInsightSlot: ApiDiffInsightSlot,
|
|
29
37
|
private compUI: ComponentUI
|
|
30
38
|
) {}
|
|
31
39
|
|
|
32
40
|
static runtime = UIRuntime;
|
|
33
41
|
|
|
34
|
-
static slots = [
|
|
42
|
+
static slots = [
|
|
43
|
+
Slot.withType<ComponentCompareNavSlot>(),
|
|
44
|
+
Slot.withType<RouteSlot>(),
|
|
45
|
+
Slot.withType<TabItem | TabItem[]>(),
|
|
46
|
+
Slot.withType<ApiDiffInsight | ApiDiffInsight[]>(),
|
|
47
|
+
];
|
|
35
48
|
|
|
36
49
|
static dependencies = [ComponentAspect];
|
|
37
50
|
|
|
38
51
|
getComponentComparePage = (props?: ComponentCompareProps & { pinned?: boolean }) => {
|
|
39
|
-
const tabs = props?.tabs || (() =>
|
|
40
|
-
const routes = props?.routes || (() => flatten(this.routeSlot.values()));
|
|
52
|
+
const tabs = props?.tabs || (() => this.resolveCompareTabs());
|
|
41
53
|
const host = props?.host || this.host;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
host={host}
|
|
49
|
-
isFullScreen={props?.isFullScreen ?? true}
|
|
50
|
-
/>
|
|
51
|
-
);
|
|
54
|
+
// The API compare tab is contributed by the api-reference aspect via `registerNavigation`
|
|
55
|
+
// (navSlot), which the redesign page's view-mode toolbar doesn't read. Hand it the API element
|
|
56
|
+
// lazily so it's resolved at render time — after every aspect's UI provider has registered,
|
|
57
|
+
// regardless of provider order — and rendered as a page-local `api` view mode.
|
|
58
|
+
const getApiTab = () => this.tabs.find((tab) => tab.id === 'api')?.element;
|
|
59
|
+
return <ComponentComparePage tabs={tabs} host={host} getApiTab={getApiTab} />;
|
|
52
60
|
};
|
|
53
61
|
|
|
54
62
|
getAspectsComparePage = () => {
|
|
@@ -73,6 +81,68 @@ export class ComponentCompareUI {
|
|
|
73
81
|
return this;
|
|
74
82
|
}
|
|
75
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Register an inline-compare tab. The tab's `id` should match the new toolbar view-mode ids
|
|
86
|
+
* (`inline-code`, `inline-preview`, `inline-docs`, `inline-deps`, `inline-tests`, `inline-config`).
|
|
87
|
+
* Used by both the single-component compare page and lane-compare.
|
|
88
|
+
*/
|
|
89
|
+
registerCompareTab(tab: TabItem | TabItem[]) {
|
|
90
|
+
this.compareTabSlot.register(tab);
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* contribute intelligence to the API diff view: per-change renderers for migration
|
|
96
|
+
* hints, affected dependents, codemods, etc. rendered in each change block's
|
|
97
|
+
* insights area (lane compare API view and the single-component API tab).
|
|
98
|
+
*/
|
|
99
|
+
registerApiDiffInsight(insight: ApiDiffInsight | ApiDiffInsight[]) {
|
|
100
|
+
this.apiDiffInsightSlot.register(insight);
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private _resolvedApiDiffInsights?: ApiDiffInsight[];
|
|
105
|
+
private _resolvedApiDiffInsightsKey?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Memoized by slot-entry count (mirroring `resolveCompareTabs`) so the returned array keeps a
|
|
108
|
+
* stable identity across renders — `LaneCompare` is React.memo'd, and a fresh array on every
|
|
109
|
+
* call would break its shallow compare and re-render the whole compare tree.
|
|
110
|
+
*/
|
|
111
|
+
getApiDiffInsights(): ApiDiffInsight[] {
|
|
112
|
+
const slotEntries = this.apiDiffInsightSlot.toArray();
|
|
113
|
+
if (this._resolvedApiDiffInsights && this._resolvedApiDiffInsightsKey === slotEntries.length) {
|
|
114
|
+
return this._resolvedApiDiffInsights;
|
|
115
|
+
}
|
|
116
|
+
this._resolvedApiDiffInsights = flatten(
|
|
117
|
+
slotEntries.map(([, value]) => value) as Array<ApiDiffInsight | ApiDiffInsight[]>
|
|
118
|
+
);
|
|
119
|
+
this._resolvedApiDiffInsightsKey = slotEntries.length;
|
|
120
|
+
return this._resolvedApiDiffInsights;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private _resolvedCompareTabs?: TabItem[];
|
|
124
|
+
private _resolvedCompareTabsKey?: number;
|
|
125
|
+
/**
|
|
126
|
+
* Resolve the inline-compare tabs that aspects register via `registerCompareTab` (code →
|
|
127
|
+
* inline-code/deps/tests/config, compositions → inline-preview, docs → inline-docs, …). Dedup by
|
|
128
|
+
* id (first registration wins), sort by order. Memoized by slot-entry count so the resolved list
|
|
129
|
+
* keeps a stable identity across renders. Owning each tab in its aspect keeps component-compare
|
|
130
|
+
* decoupled from code/preview/docs UI; single-component compare and lane-compare both read this.
|
|
131
|
+
*/
|
|
132
|
+
resolveCompareTabs(): TabItem[] {
|
|
133
|
+
const slotEntries = this.compareTabSlot.toArray();
|
|
134
|
+
if (this._resolvedCompareTabs && this._resolvedCompareTabsKey === slotEntries.length) {
|
|
135
|
+
return this._resolvedCompareTabs;
|
|
136
|
+
}
|
|
137
|
+
const registered = flatten(slotEntries.map(([, value]) => value).filter(Boolean) as Array<TabItem | TabItem[]>);
|
|
138
|
+
const seen = new Set<string>();
|
|
139
|
+
const deduped = registered.filter((tab) => (seen.has(tab.id) ? false : (seen.add(tab.id), true)));
|
|
140
|
+
const merged = deduped.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
141
|
+
this._resolvedCompareTabs = merged;
|
|
142
|
+
this._resolvedCompareTabsKey = slotEntries.length;
|
|
143
|
+
return merged;
|
|
144
|
+
}
|
|
145
|
+
|
|
76
146
|
get routes() {
|
|
77
147
|
return this.routeSlot.map;
|
|
78
148
|
}
|
|
@@ -106,12 +176,24 @@ export class ComponentCompareUI {
|
|
|
106
176
|
static async provider(
|
|
107
177
|
[componentUi]: [ComponentUI],
|
|
108
178
|
_,
|
|
109
|
-
[navSlot, routeSlot]: [
|
|
179
|
+
[navSlot, routeSlot, compareTabSlot, apiDiffInsightSlot]: [
|
|
180
|
+
ComponentCompareNavSlot,
|
|
181
|
+
RouteSlot,
|
|
182
|
+
ComponentCompareTabSlot,
|
|
183
|
+
ApiDiffInsightSlot,
|
|
184
|
+
],
|
|
110
185
|
harmony: Harmony
|
|
111
186
|
) {
|
|
112
187
|
const { config } = harmony;
|
|
113
188
|
const host = String(config.get('teambit.harmony/bit'));
|
|
114
|
-
const componentCompareUI = new ComponentCompareUI(
|
|
189
|
+
const componentCompareUI = new ComponentCompareUI(
|
|
190
|
+
host,
|
|
191
|
+
navSlot,
|
|
192
|
+
routeSlot,
|
|
193
|
+
compareTabSlot,
|
|
194
|
+
apiDiffInsightSlot,
|
|
195
|
+
componentUi
|
|
196
|
+
);
|
|
115
197
|
const componentCompareSection = new ComponentCompareSection(componentCompareUI, false);
|
|
116
198
|
const pinnedComponentCompareSection = new ComponentCompareSection(componentCompareUI, true);
|
|
117
199
|
componentUi.registerRoute([componentCompareSection.route]);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ComponentComparePair = {
|
|
2
|
+
baseId: string;
|
|
3
|
+
compareId: string;
|
|
4
|
+
};
|
|
5
|
+
export type CompareComponentPairsOptions = {
|
|
6
|
+
/** index into `pairs` to start from (default 0) */
|
|
7
|
+
offset?: number;
|
|
8
|
+
/** number of pairs to process from `offset` (default: the rest of the list) */
|
|
9
|
+
limit?: number;
|
|
10
|
+
/** max number of pairs compared in parallel */
|
|
11
|
+
concurrency: number;
|
|
12
|
+
/** invoked when a single pair's comparison throws; that pair's slot becomes null */
|
|
13
|
+
onError?: (pair: ComponentComparePair, err: unknown) => void;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* compares a paginated slice of component pairs with bounded concurrency.
|
|
17
|
+
* a pair whose `compareFn` throws becomes `null` in the result instead of failing the whole batch.
|
|
18
|
+
* the returned array is aligned to the requested slice (`pairs[offset .. offset + limit]`).
|
|
19
|
+
*/
|
|
20
|
+
export declare function compareComponentPairs<T>(pairs: ComponentComparePair[], compareFn: (baseId: string, compareId: string) => Promise<T>, options: CompareComponentPairsOptions): Promise<Array<T | null>>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.compareComponentPairs = compareComponentPairs;
|
|
7
|
+
function _pMap() {
|
|
8
|
+
const data = _interopRequireDefault(require("p-map"));
|
|
9
|
+
_pMap = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
/**
|
|
16
|
+
* compares a paginated slice of component pairs with bounded concurrency.
|
|
17
|
+
* a pair whose `compareFn` throws becomes `null` in the result instead of failing the whole batch.
|
|
18
|
+
* the returned array is aligned to the requested slice (`pairs[offset .. offset + limit]`).
|
|
19
|
+
*/
|
|
20
|
+
async function compareComponentPairs(pairs, compareFn, options) {
|
|
21
|
+
const offset = options.offset ?? 0;
|
|
22
|
+
const limit = options.limit ?? pairs.length - offset;
|
|
23
|
+
const slice = pairs.slice(offset, offset + limit);
|
|
24
|
+
return (0, _pMap().default)(slice, async pair => {
|
|
25
|
+
try {
|
|
26
|
+
return await compareFn(pair.baseId, pair.compareId);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
options.onError?.(pair, err);
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}, {
|
|
32
|
+
concurrency: options.concurrency
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=compare-component-pairs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_pMap","data","_interopRequireDefault","require","e","__esModule","default","compareComponentPairs","pairs","compareFn","options","offset","limit","length","slice","pMap","pair","baseId","compareId","err","onError","concurrency"],"sources":["compare-component-pairs.ts"],"sourcesContent":["import pMap from 'p-map';\n\nexport type ComponentComparePair = {\n baseId: string;\n compareId: string;\n};\n\nexport type CompareComponentPairsOptions = {\n /** index into `pairs` to start from (default 0) */\n offset?: number;\n /** number of pairs to process from `offset` (default: the rest of the list) */\n limit?: number;\n /** max number of pairs compared in parallel */\n concurrency: number;\n /** invoked when a single pair's comparison throws; that pair's slot becomes null */\n onError?: (pair: ComponentComparePair, err: unknown) => void;\n};\n\n/**\n * compares a paginated slice of component pairs with bounded concurrency.\n * a pair whose `compareFn` throws becomes `null` in the result instead of failing the whole batch.\n * the returned array is aligned to the requested slice (`pairs[offset .. offset + limit]`).\n */\nexport async function compareComponentPairs<T>(\n pairs: ComponentComparePair[],\n compareFn: (baseId: string, compareId: string) => Promise<T>,\n options: CompareComponentPairsOptions\n): Promise<Array<T | null>> {\n const offset = options.offset ?? 0;\n const limit = options.limit ?? pairs.length - offset;\n const slice = pairs.slice(offset, offset + limit);\n\n return pMap(\n slice,\n async (pair): Promise<T | null> => {\n try {\n return await compareFn(pair.baseId, pair.compareId);\n } catch (err) {\n options.onError?.(pair, err);\n return null;\n }\n },\n { concurrency: options.concurrency }\n );\n}\n"],"mappings":";;;;;;AAAA,SAAAA,MAAA;EAAA,MAAAC,IAAA,GAAAC,sBAAA,CAAAC,OAAA;EAAAH,KAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAyB,SAAAC,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAkBzB;AACA;AACA;AACA;AACA;AACO,eAAeG,qBAAqBA,CACzCC,KAA6B,EAC7BC,SAA4D,EAC5DC,OAAqC,EACX;EAC1B,MAAMC,MAAM,GAAGD,OAAO,CAACC,MAAM,IAAI,CAAC;EAClC,MAAMC,KAAK,GAAGF,OAAO,CAACE,KAAK,IAAIJ,KAAK,CAACK,MAAM,GAAGF,MAAM;EACpD,MAAMG,KAAK,GAAGN,KAAK,CAACM,KAAK,CAACH,MAAM,EAAEA,MAAM,GAAGC,KAAK,CAAC;EAEjD,OAAO,IAAAG,eAAI,EACTD,KAAK,EACL,MAAOE,IAAI,IAAwB;IACjC,IAAI;MACF,OAAO,MAAMP,SAAS,CAACO,IAAI,CAACC,MAAM,EAAED,IAAI,CAACE,SAAS,CAAC;IACrD,CAAC,CAAC,OAAOC,GAAG,EAAE;MACZT,OAAO,CAACU,OAAO,GAAGJ,IAAI,EAAEG,GAAG,CAAC;MAC5B,OAAO,IAAI;IACb;EACF,CAAC,EACD;IAAEE,WAAW,EAAEX,OAAO,CAACW;EAAY,CACrC,CAAC;AACH","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _chai() {
|
|
4
|
+
const data = require("chai");
|
|
5
|
+
_chai = function () {
|
|
6
|
+
return data;
|
|
7
|
+
};
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
function _compareComponentPairs() {
|
|
11
|
+
const data = require("./compare-component-pairs");
|
|
12
|
+
_compareComponentPairs = function () {
|
|
13
|
+
return data;
|
|
14
|
+
};
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
describe('compareComponentPairs', () => {
|
|
18
|
+
const pairs = [{
|
|
19
|
+
baseId: 'a@1',
|
|
20
|
+
compareId: 'a@2'
|
|
21
|
+
}, {
|
|
22
|
+
baseId: 'b@1',
|
|
23
|
+
compareId: 'b@2'
|
|
24
|
+
}, {
|
|
25
|
+
baseId: 'c@1',
|
|
26
|
+
compareId: 'c@2'
|
|
27
|
+
}];
|
|
28
|
+
it('returns one result per pair, preserving order', async () => {
|
|
29
|
+
const results = await (0, _compareComponentPairs().compareComponentPairs)(pairs, async (baseId, compareId) => ({
|
|
30
|
+
id: `${baseId}-${compareId}`
|
|
31
|
+
}), {
|
|
32
|
+
concurrency: 2
|
|
33
|
+
});
|
|
34
|
+
(0, _chai().expect)(results).to.deep.equal([{
|
|
35
|
+
id: 'a@1-a@2'
|
|
36
|
+
}, {
|
|
37
|
+
id: 'b@1-b@2'
|
|
38
|
+
}, {
|
|
39
|
+
id: 'c@1-c@2'
|
|
40
|
+
}]);
|
|
41
|
+
});
|
|
42
|
+
it('slices by offset and limit', async () => {
|
|
43
|
+
const results = await (0, _compareComponentPairs().compareComponentPairs)(pairs, async baseId => ({
|
|
44
|
+
id: baseId
|
|
45
|
+
}), {
|
|
46
|
+
offset: 1,
|
|
47
|
+
limit: 1,
|
|
48
|
+
concurrency: 2
|
|
49
|
+
});
|
|
50
|
+
(0, _chai().expect)(results).to.deep.equal([{
|
|
51
|
+
id: 'b@1'
|
|
52
|
+
}]);
|
|
53
|
+
});
|
|
54
|
+
it('returns an empty array when offset is past the end', async () => {
|
|
55
|
+
const results = await (0, _compareComponentPairs().compareComponentPairs)(pairs, async b => ({
|
|
56
|
+
id: b
|
|
57
|
+
}), {
|
|
58
|
+
offset: 99,
|
|
59
|
+
concurrency: 2
|
|
60
|
+
});
|
|
61
|
+
(0, _chai().expect)(results).to.deep.equal([]);
|
|
62
|
+
});
|
|
63
|
+
it('isolates a failing pair as null without failing the others', async () => {
|
|
64
|
+
const errors = [];
|
|
65
|
+
const results = await (0, _compareComponentPairs().compareComponentPairs)(pairs, async baseId => {
|
|
66
|
+
if (baseId === 'b@1') throw new Error('no version yet');
|
|
67
|
+
return {
|
|
68
|
+
id: baseId
|
|
69
|
+
};
|
|
70
|
+
}, {
|
|
71
|
+
concurrency: 2,
|
|
72
|
+
onError: pair => errors.push(pair)
|
|
73
|
+
});
|
|
74
|
+
(0, _chai().expect)(results).to.deep.equal([{
|
|
75
|
+
id: 'a@1'
|
|
76
|
+
}, null, {
|
|
77
|
+
id: 'c@1'
|
|
78
|
+
}]);
|
|
79
|
+
(0, _chai().expect)(errors).to.deep.equal([{
|
|
80
|
+
baseId: 'b@1',
|
|
81
|
+
compareId: 'b@2'
|
|
82
|
+
}]);
|
|
83
|
+
});
|
|
84
|
+
it('returns an empty array for empty input', async () => {
|
|
85
|
+
const results = await (0, _compareComponentPairs().compareComponentPairs)([], async b => ({
|
|
86
|
+
id: b
|
|
87
|
+
}), {
|
|
88
|
+
concurrency: 2
|
|
89
|
+
});
|
|
90
|
+
(0, _chai().expect)(results).to.deep.equal([]);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=compare-component-pairs.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_chai","data","require","_compareComponentPairs","describe","pairs","baseId","compareId","it","results","compareComponentPairs","id","concurrency","expect","to","deep","equal","offset","limit","b","errors","Error","onError","pair","push"],"sources":["compare-component-pairs.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport { compareComponentPairs } from './compare-component-pairs';\nimport type { ComponentComparePair } from './compare-component-pairs';\n\ndescribe('compareComponentPairs', () => {\n const pairs: ComponentComparePair[] = [\n { baseId: 'a@1', compareId: 'a@2' },\n { baseId: 'b@1', compareId: 'b@2' },\n { baseId: 'c@1', compareId: 'c@2' },\n ];\n\n it('returns one result per pair, preserving order', async () => {\n const results = await compareComponentPairs(\n pairs,\n async (baseId, compareId) => ({ id: `${baseId}-${compareId}` }),\n { concurrency: 2 }\n );\n expect(results).to.deep.equal([{ id: 'a@1-a@2' }, { id: 'b@1-b@2' }, { id: 'c@1-c@2' }]);\n });\n\n it('slices by offset and limit', async () => {\n const results = await compareComponentPairs(pairs, async (baseId) => ({ id: baseId }), {\n offset: 1,\n limit: 1,\n concurrency: 2,\n });\n expect(results).to.deep.equal([{ id: 'b@1' }]);\n });\n\n it('returns an empty array when offset is past the end', async () => {\n const results = await compareComponentPairs(pairs, async (b) => ({ id: b }), {\n offset: 99,\n concurrency: 2,\n });\n expect(results).to.deep.equal([]);\n });\n\n it('isolates a failing pair as null without failing the others', async () => {\n const errors: ComponentComparePair[] = [];\n const results = await compareComponentPairs(\n pairs,\n async (baseId) => {\n if (baseId === 'b@1') throw new Error('no version yet');\n return { id: baseId };\n },\n {\n concurrency: 2,\n onError: (pair) => errors.push(pair),\n }\n );\n expect(results).to.deep.equal([{ id: 'a@1' }, null, { id: 'c@1' }]);\n expect(errors).to.deep.equal([{ baseId: 'b@1', compareId: 'b@2' }]);\n });\n\n it('returns an empty array for empty input', async () => {\n const results = await compareComponentPairs([], async (b) => ({ id: b }), { concurrency: 2 });\n expect(results).to.deep.equal([]);\n });\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import type { TabItem } from '@teambit/component.ui.component-compare.models.component-compare-props';
|
|
4
|
+
export type ComponentComparePageProps = {
|
|
5
|
+
host: string;
|
|
6
|
+
tabs: TabItem[] | (() => TabItem[]);
|
|
7
|
+
/**
|
|
8
|
+
* Lazily resolves the API compare element (contributed by the api-reference aspect). Resolved at
|
|
9
|
+
* render — not construction — so it doesn't depend on UI-provider registration order. When it
|
|
10
|
+
* yields an element, the page exposes an `api` view mode; the element is only mounted while that
|
|
11
|
+
* view is active, so its diff query fires on-demand.
|
|
12
|
+
*/
|
|
13
|
+
getApiTab?: () => React.ReactNode;
|
|
14
|
+
className?: string;
|
|
15
|
+
} & HTMLAttributes<HTMLDivElement>;
|
|
16
|
+
export declare function ComponentComparePage({ host: hostFromProps, tabs, getApiTab, className, ...rest }: ComponentComparePageProps): React.JSX.Element;
|