Skip to content

Commit 4427fe1

Browse files
griest024xelaint
andauthored
feat(daffio): render subpackages on package page (#3094)
--------- Co-authored-by: xelaint <[email protected]>
1 parent 92b0c42 commit 4427fe1

13 files changed

+306
-18
lines changed

apps/daffio/src/app/docs/api/components/api-list-section/api-list-section.component.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ $api-list-section-item-border-radius: 4px;
4141
top: 0;
4242
height: 100%;
4343
width: 100%;
44-
transition: opacity 300ms;
44+
transition: opacity 150ms;
4545
z-index: 1;
4646
}
4747

apps/daffio/src/app/docs/api/components/api-list/api-list.component.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
@include daff.text-truncate();
3333

3434
@include daff.breakpoint(mobile) {
35-
display: inline-block;
35+
display: inline;
3636
}
3737
}
3838
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
@use 'theme' as daff-theme;
2+
3+
@mixin daffio-api-package-theme($theme) {
4+
$neutral: daff-theme.daff-map-deep-get($theme, 'core.neutral');
5+
$base: daff-theme.daff-map-deep-get($theme, "core.base");
6+
$base-contrast: daff-theme.daff-map-deep-get($theme, "core.base-contrast");
7+
8+
.daffio-api-package {
9+
&__subpackage-name {
10+
> * {
11+
&:focus {
12+
border-radius: 4px;
13+
box-shadow: 0 0 0 4px rgba($base-contrast, 0.1);
14+
outline: none;
15+
}
16+
}
17+
18+
&:hover {
19+
color: daff-theme.daff-illuminate($base-contrast, $neutral, 3);
20+
}
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<div class="daffio-api-package__wrapper">
2+
<div class="daffio-api-package__header">
3+
<h1 class="daffio-api-package__package-name">{{doc.title}}</h1>
4+
<p *ngIf="doc.description" class="daffio-api-package__package-description">{{doc.description}}</p>
5+
</div>
6+
<daffio-api-list-section [children]="doc.children | apiPackageFilter:true" class="daffio-doc-viewer__api-section"></daffio-api-list-section>
7+
</div>
8+
9+
@for (package of doc.children | apiPackageFilter; track package.id) {
10+
<div class="daffio-api-package__wrapper">
11+
<h2 class="daffio-api-package__subpackage-name">
12+
<a [routerLink]="package.path">{{package.title}}</a>
13+
</h2>
14+
<daffio-api-list-section [children]="package.children | apiPackageFilter:true" class="daffio-doc-viewer__api-section" [attr.data-section-for-subpackage]="package.id"></daffio-api-list-section>
15+
</div>
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
@use '../../../../../scss/type-descriptors/mixins' as type-mixin;
2+
@use 'utilities' as daff;
3+
4+
:host {
5+
display: flex;
6+
flex-direction: column;
7+
gap: 48px;
8+
9+
a {
10+
text-decoration: none;
11+
}
12+
}
13+
14+
.daffio-api-package {
15+
&__wrapper {
16+
display: flex;
17+
flex-direction: column;
18+
gap: 24px;
19+
}
20+
21+
&__header {
22+
display: flex;
23+
flex-direction: column;
24+
gap: 16px;
25+
}
26+
27+
&__package-name {
28+
@include daff.headline-lg;
29+
30+
> * {
31+
@include daff.text-truncate();
32+
33+
@include daff.breakpoint(mobile) {
34+
display: inline;
35+
}
36+
}
37+
}
38+
39+
&__package-description {
40+
@include daff.body-md;
41+
font-weight: 400;
42+
margin: 0;
43+
padding: 0;
44+
}
45+
46+
&__subpackage-name {
47+
font-size: 1.125rem;
48+
font-weight: 600;
49+
line-height: 1.375rem;
50+
51+
@include daff.breakpoint(mobile) {
52+
font-size: 1.25rem;
53+
line-height: 1.75rem;
54+
}
55+
56+
> * {
57+
@include daff.text-truncate();
58+
59+
@include daff.breakpoint(mobile) {
60+
display: inline-block;
61+
}
62+
}
63+
}
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import {
2+
Component,
3+
DebugElement,
4+
} from '@angular/core';
5+
import {
6+
ComponentFixture,
7+
TestBed,
8+
waitForAsync,
9+
} from '@angular/core/testing';
10+
import { By } from '@angular/platform-browser';
11+
import { RouterTestingModule } from '@angular/router/testing';
12+
13+
import { DaffioApiPackageComponent } from './api-package.component';
14+
import { DaffioApiReference } from '../../models/api-reference';
15+
import { DaffioApiListSectionComponent } from '../api-list-section/api-list-section.component';
16+
17+
@Component({
18+
template: `
19+
<daffio-api-package [doc]="apiListValue"></daffio-api-package>
20+
`,
21+
standalone: true,
22+
imports: [
23+
DaffioApiPackageComponent,
24+
],
25+
})
26+
class WrapperComponent {
27+
apiListValue: DaffioApiReference;
28+
}
29+
30+
describe('DaffioApiPackageComponent', () => {
31+
let wrapper: WrapperComponent;
32+
let fixture: ComponentFixture<WrapperComponent>;
33+
let component: DaffioApiPackageComponent;
34+
let packageLinks: Array<DebugElement>;
35+
36+
beforeEach(waitForAsync(() => {
37+
TestBed.configureTestingModule({
38+
imports: [
39+
WrapperComponent,
40+
RouterTestingModule,
41+
],
42+
})
43+
.compileComponents();
44+
}));
45+
46+
beforeEach(() => {
47+
fixture = TestBed.createComponent(WrapperComponent);
48+
wrapper = fixture.componentInstance;
49+
wrapper.apiListValue = {
50+
id: 'Root',
51+
path: 'path',
52+
docType: 'package',
53+
docTypeShorthand: 'pk',
54+
title: 'title',
55+
description: 'description',
56+
children: [
57+
{
58+
id: 'name1Component',
59+
title: 'title1Component',
60+
path: 'path1',
61+
docType: 'docType1',
62+
docTypeShorthand: 'dt',
63+
children: [],
64+
},
65+
{
66+
id: 'name2Module',
67+
title: 'title2Module',
68+
path: 'path2',
69+
docType: 'package',
70+
docTypeShorthand: 'pk',
71+
children: [
72+
{
73+
id: 'name1Component',
74+
title: 'title1Component',
75+
path: 'path1',
76+
docType: 'docType1',
77+
docTypeShorthand: 'dt',
78+
children: [],
79+
},
80+
{
81+
id: 'name2Module',
82+
title: 'title2Module',
83+
path: 'path2',
84+
docType: 'package',
85+
docTypeShorthand: 'pk',
86+
children: [],
87+
},
88+
],
89+
},
90+
],
91+
};
92+
fixture.detectChanges();
93+
94+
component = fixture.debugElement.query(By.css('daffio-api-package')).componentInstance;
95+
packageLinks = fixture.debugElement.queryAll(By.css('a.daffio-api-package__package-name'));
96+
});
97+
98+
it('should create', () => {
99+
expect(component).toBeTruthy();
100+
});
101+
102+
it('should be able to take doc as input', () => {
103+
expect(component.doc).toEqual(wrapper.apiListValue);
104+
});
105+
106+
describe('for every subpackage in children', () => {
107+
let subpackages: Array<DaffioApiReference>;
108+
109+
beforeEach(() => {
110+
subpackages = wrapper.apiListValue.children.filter((d) => d.docType === 'package');
111+
});
112+
113+
it('should render a link with the title', () => {
114+
packageLinks.forEach((de, i) => {
115+
expect(de.nativeElement.innerText).toEqual(subpackages[i].title);
116+
expect(de.attributes['ng-reflect-router-link']).toEqual(subpackages[i].path);
117+
});
118+
});
119+
120+
it('should render an API section with the subpackage children excluding packages', () => {
121+
packageLinks.forEach((de, i) => {
122+
const apiSection: DaffioApiListSectionComponent = fixture.debugElement.query(By.css(`daffio-api-list-section[data-section-for-subpackage="${subpackages[i].id}"]`)).componentInstance;
123+
expect(apiSection.children).toEqual(subpackages[i].children.filter((c) => c.docType !== 'package'));
124+
});
125+
});
126+
});
127+
128+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
Component,
3+
Input,
4+
ChangeDetectionStrategy,
5+
HostBinding,
6+
} from '@angular/core';
7+
import { RouterLink } from '@angular/router';
8+
9+
import { DaffArticleEncapsulatedDirective } from '@daffodil/design';
10+
import { DaffArticleModule } from '@daffodil/design/article';
11+
12+
import { DaffioApiPackageFilterPipe } from './not-packages.pipe';
13+
import { DaffioApiReference } from '../../models/api-reference';
14+
import { DaffioApiListSectionComponent } from '../api-list-section/api-list-section.component';
15+
16+
@Component({
17+
selector: 'daffio-api-package',
18+
templateUrl: './api-package.component.html',
19+
styleUrls: ['./api-package.component.scss'],
20+
hostDirectives: [{
21+
directive: DaffArticleEncapsulatedDirective,
22+
}],
23+
changeDetection: ChangeDetectionStrategy.OnPush,
24+
standalone: true,
25+
imports: [
26+
RouterLink,
27+
DaffioApiListSectionComponent,
28+
DaffArticleModule,
29+
DaffioApiPackageFilterPipe,
30+
],
31+
})
32+
export class DaffioApiPackageComponent {
33+
@HostBinding('class.daffio-api-package') class = true;
34+
35+
/**
36+
* A list of references for API documents.
37+
*/
38+
@Input() doc: DaffioApiReference;
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import {
2+
Pipe,
3+
PipeTransform,
4+
} from '@angular/core';
5+
6+
import { DaffioApiReference } from '../../models/api-reference';
7+
8+
/**
9+
* Filters packages from a list of API docs.
10+
* If exclude is false or omitted, will only output packages.
11+
* Otherwise it will omit packages from the output.
12+
*/
13+
@Pipe({
14+
name: 'apiPackageFilter',
15+
standalone: true,
16+
})
17+
export class DaffioApiPackageFilterPipe implements PipeTransform {
18+
transform(docs: Array<DaffioApiReference>, exclude = false) {
19+
return exclude
20+
? docs.filter((doc) => doc.docType !== 'package')
21+
: docs.filter((doc) => doc.docType === 'package');
22+
}
23+
}

apps/daffio/src/app/docs/api/models/api-reference.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ import { DaffioGenericDocList } from '../../models/doc-list';
66
export interface DaffioApiReference extends DaffioGenericDocList<DaffioApiReference> {
77
docType: string;
88
docTypeShorthand: string;
9+
description?: string;
910
}

apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.html

+1-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
</button>
55
<div class="daffio-doc-viewer__grid">
66
@if (isApiPackage) {
7-
<daff-article class="daffio-doc-viewer__content">
8-
<h1>{{doc.title}}</h1>
9-
<p>{{doc.description}}</p>
10-
<daffio-api-list-section [children]="doc.children" class="daffio-doc-viewer__api-section"></daffio-api-list-section>
11-
</daff-article>
7+
<daffio-api-package [doc]="doc"></daffio-api-package>
128
} @else {
139
<daff-article
1410
class="daffio-doc-viewer__content"

apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.component.spec.ts

+5-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { provideMockStore } from '@ngrx/store/testing';
1111
import { DaffArticleModule } from '@daffodil/design/article';
1212

1313
import { DaffioDocViewerComponent } from './doc-viewer.component';
14-
import { DaffioApiListSectionComponent } from '../../api/components/api-list-section/api-list-section.component';
14+
import { DaffioApiPackageComponent } from '../../api/components/api-package/api-package.component';
1515
import { DaffioApiReference } from '../../api/models/api-reference';
1616
import { DaffioDoc } from '../../models/doc';
1717
import { DaffioDocsFactory } from '../../testing/factories/docs.factory';
@@ -35,7 +35,7 @@ describe('DaffioDocViewerComponent', () => {
3535
RouterTestingModule,
3636
DaffArticleModule,
3737
DaffioDocsTableOfContentsModule,
38-
DaffioApiListSectionComponent,
38+
DaffioApiPackageComponent,
3939
],
4040
declarations: [
4141
WrapperComponent,
@@ -81,13 +81,9 @@ describe('DaffioDocViewerComponent', () => {
8181
fixture.detectChanges();
8282
});
8383

84-
it('should render the package name', () => {
85-
expect(fixture.debugElement.query(By.css('.daffio-doc-viewer__content h1')).nativeElement.innerText).toEqual(wrapper.doc.title);
86-
});
87-
88-
it('should render the package doc children', () => {
89-
const apiChildren: DaffioApiListSectionComponent = fixture.debugElement.query(By.directive(DaffioApiListSectionComponent)).componentInstance;
90-
expect(apiChildren.children).toEqual((<DaffioApiReference>wrapper.doc).children);
84+
it('should render the package doc', () => {
85+
const apiChildren: DaffioApiPackageComponent = fixture.debugElement.query(By.directive(DaffioApiPackageComponent)).componentInstance;
86+
expect(apiChildren.doc).toEqual((<DaffioApiReference>wrapper.doc));
9187
});
9288
});
9389

apps/daffio/src/app/docs/components/doc-viewer/doc-viewer.module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { DaffContainerModule } from '@daffodil/design/container';
88
import { DaffSidebarModule } from '@daffodil/design/sidebar';
99

1010
import { DaffioDocViewerComponent } from './doc-viewer.component';
11-
import { DaffioApiListSectionComponent } from '../../api/components/api-list-section/api-list-section.component';
11+
import { DaffioApiPackageComponent } from '../../api/components/api-package/api-package.component';
1212
import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-contents.module';
1313

1414
@NgModule({
@@ -23,7 +23,7 @@ import { DaffioDocsTableOfContentsModule } from '../table-of-contents/table-of-c
2323
DaffArticleModule,
2424
DaffContainerModule,
2525
DaffioDocsTableOfContentsModule,
26-
DaffioApiListSectionComponent,
26+
DaffioApiPackageComponent,
2727
DaffSidebarModule,
2828
DaffButtonModule,
2929
FontAwesomeModule,

0 commit comments

Comments
 (0)