create-sitecore-jss 22.2.0-canary.8 → 22.2.0-canary.80

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 (119) hide show
  1. package/dist/bin.js +17 -43
  2. package/dist/common/processes/next.js +4 -1
  3. package/dist/common/processes/transform.js +2 -12
  4. package/dist/common/prompts/base.js +0 -13
  5. package/dist/common/prompts/proxy.js +35 -0
  6. package/dist/common/prompts/sxp.js +16 -2
  7. package/dist/common/utils/helpers.js +27 -2
  8. package/dist/init-runner.js +1 -1
  9. package/dist/initializers/angular/prompts.js +4 -4
  10. package/dist/initializers/angular-xmcloud/index.js +21 -7
  11. package/dist/initializers/node-xmcloud-proxy/index.js +2 -1
  12. package/dist/templates/angular/.env +4 -5
  13. package/dist/templates/angular/.eslintrc +1 -0
  14. package/dist/templates/angular/gitignore +5 -0
  15. package/dist/templates/angular/package.json +1 -3
  16. package/dist/templates/angular/scripts/config/plugins/fallback.ts +0 -1
  17. package/dist/templates/angular/scripts/generate-component-factory/index.ts +45 -0
  18. package/dist/templates/angular/scripts/generate-component-factory/plugins/component-factory.ts +147 -0
  19. package/dist/templates/angular/scripts/generate-component-factory/plugins/components.ts +19 -0
  20. package/dist/templates/angular/scripts/generate-component-factory/plugins/packages.ts +29 -0
  21. package/dist/templates/angular/scripts/generate-component-factory/template.ts +46 -0
  22. package/dist/templates/angular/scripts/generate-config.ts +25 -6
  23. package/dist/templates/angular/scripts/generate-plugins.ts +5 -0
  24. package/dist/templates/angular/scripts/update-graphql-fragment-data.ts +21 -30
  25. package/dist/templates/angular/server.bundle.ts +3 -23
  26. package/dist/templates/angular/server.exports.ts +13 -0
  27. package/dist/templates/angular/src/app/JssState.ts +2 -9
  28. package/dist/templates/angular/src/app/app.module.ts +5 -4
  29. package/dist/templates/angular/src/app/app.server.module.ts +9 -6
  30. package/dist/templates/angular/src/app/components/gitignore +1 -1
  31. package/dist/templates/angular/src/app/i18n/jss-translation-client-loader.service.ts +15 -7
  32. package/dist/templates/angular/src/app/i18n/jss-translation-server-loader.service.ts +14 -2
  33. package/dist/templates/angular/src/app/jss-context.server-side.service.ts +4 -2
  34. package/dist/templates/angular/src/app/jss-context.service.ts +14 -11
  35. package/dist/templates/angular/src/app/jss-graphql.service.ts +7 -7
  36. package/dist/templates/angular/src/app/layout/jss-layout.service.ts +2 -2
  37. package/dist/templates/angular/src/app/lib/dictionary-service-factory.ts +4 -1
  38. package/dist/templates/angular/src/app/lib/graphql-client-factory/config.ts +21 -0
  39. package/dist/templates/angular/src/app/lib/graphql-client-factory/index.ts +16 -0
  40. package/dist/templates/angular/src/app/lib/layout-service-factory.ts +1 -1
  41. package/dist/templates/angular/src/app/routing/layout/layout.component.ts +10 -9
  42. package/dist/templates/angular/src/environments/gitignore +2 -1
  43. package/dist/templates/angular-sxp/.env +2 -0
  44. package/dist/templates/angular-sxp/scripts/config/plugins/disconnected.ts +4 -2
  45. package/dist/templates/angular-sxp/src/app/components/graph-ql-layout/graph-ql-layout.component.ts +1 -1
  46. package/dist/templates/angular-xmcloud/.env +15 -2
  47. package/dist/templates/angular-xmcloud/angular.json +0 -1
  48. package/dist/templates/angular-xmcloud/package.json +2 -0
  49. package/dist/templates/angular-xmcloud/scripts/bootstrap.ts +28 -0
  50. package/dist/templates/angular-xmcloud/scripts/config/plugins/xmcloud.ts +16 -0
  51. package/dist/templates/angular-xmcloud/scripts/generate-component-factory/plugins/packages.ts +34 -0
  52. package/dist/templates/angular-xmcloud/scripts/generate-component-factory/template.ts +57 -0
  53. package/dist/templates/angular-xmcloud/scripts/generate-metadata.ts +25 -0
  54. package/dist/templates/angular-xmcloud/server.exports.ts +24 -0
  55. package/dist/templates/angular-xmcloud/src/app/components/app-components.shared.module.ts +21 -0
  56. package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.html +5 -0
  57. package/dist/templates/angular-xmcloud/src/app/components/column-splitter/column-splitter.component.ts +40 -0
  58. package/dist/templates/angular-xmcloud/src/app/components/container/container.component.html +2 -3
  59. package/dist/templates/angular-xmcloud/src/app/components/image/image.component.html +36 -0
  60. package/dist/templates/angular-xmcloud/src/app/components/image/image.component.ts +67 -0
  61. package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.html +15 -0
  62. package/dist/templates/angular-xmcloud/src/app/components/link-list/link-list.component.ts +41 -0
  63. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.html +23 -0
  64. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation-item.component.ts +65 -0
  65. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.html +21 -0
  66. package/dist/templates/angular-xmcloud/src/app/components/navigation/navigation.component.ts +49 -0
  67. package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.html +5 -0
  68. package/dist/templates/angular-xmcloud/src/app/components/page-content/page-content.component.ts +39 -0
  69. package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.html +1 -0
  70. package/dist/templates/angular-xmcloud/src/app/components/partial-design-dynamic-placeholder/partial-design-dynamic-placeholder.component.ts +15 -0
  71. package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.html +21 -0
  72. package/dist/templates/angular-xmcloud/src/app/components/promo/promo.component.ts +13 -0
  73. package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.html +7 -12
  74. package/dist/templates/angular-xmcloud/src/app/components/richtext/richtext.component.ts +6 -1
  75. package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.html +11 -0
  76. package/dist/templates/angular-xmcloud/src/app/components/row-splitter/row-splitter.component.ts +35 -0
  77. package/dist/templates/angular-xmcloud/src/app/components/sxa.component.ts +3 -3
  78. package/dist/templates/angular-xmcloud/src/app/components/title/title.component.html +10 -0
  79. package/dist/templates/angular-xmcloud/src/app/components/title/title.component.ts +56 -0
  80. package/dist/templates/angular-xmcloud/src/app/jss-link.service.ts +55 -0
  81. package/dist/templates/angular-xmcloud/src/app/lib/config.ts +2 -0
  82. package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory/config.ts +58 -0
  83. package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.html +38 -0
  84. package/dist/templates/angular-xmcloud/src/app/routing/layout/layout.component.ts +104 -0
  85. package/dist/templates/angular-xmcloud/src/app/routing/scripts/cdp-page-view.component.ts +77 -0
  86. package/dist/templates/angular-xmcloud/src/app/routing/scripts/cloud-sdk-init.component.ts +48 -0
  87. package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.component.html +5 -0
  88. package/dist/templates/angular-xmcloud/src/app/routing/scripts/scripts.module.ts +12 -0
  89. package/dist/templates/angular-xmcloud/src/assets/styles/basic/_header.scss +3 -1
  90. package/dist/templates/angular-xmcloud/src/assets/styles/main.scss +10 -0
  91. package/dist/templates/angular-xmcloud/src/assets/styles/sass/components/_component-image.scss +1 -1
  92. package/dist/templates/nextjs/package.json +1 -1
  93. package/dist/templates/nextjs/scripts/config/plugins/fallback.ts +0 -1
  94. package/dist/templates/nextjs/scripts/generate-config.ts +8 -1
  95. package/dist/templates/nextjs/src/lib/page-props-factory/plugins/component-props.ts +2 -1
  96. package/dist/templates/nextjs-styleguide/scripts/config/plugins/disconnected.ts +1 -0
  97. package/dist/templates/nextjs-sxa/src/assets/sass/components/_component-image.scss +1 -1
  98. package/dist/templates/nextjs-sxa/src/assets/sass/components/common/_alignment.scss +34 -7
  99. package/dist/templates/nextjs-sxa/src/components/Container.tsx +6 -14
  100. package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/component-themes.ts +2 -1
  101. package/dist/templates/nextjs-xmcloud/src/lib/page-props-factory/plugins/preview-mode.ts +2 -1
  102. package/dist/templates/node-headless-ssr-experience-edge/gitignore +19 -0
  103. package/dist/templates/node-headless-ssr-proxy/gitignore +19 -0
  104. package/dist/templates/node-headless-ssr-proxy/src/config.ts +3 -3
  105. package/dist/templates/node-headless-ssr-proxy/src/httpAgents.ts +2 -2
  106. package/dist/templates/node-headless-ssr-proxy/src/index.ts +9 -2
  107. package/dist/templates/node-xmcloud-proxy/.env +7 -1
  108. package/dist/templates/node-xmcloud-proxy/README.md +1 -1
  109. package/dist/templates/node-xmcloud-proxy/gitignore +33 -0
  110. package/dist/templates/node-xmcloud-proxy/package.json +3 -2
  111. package/dist/templates/node-xmcloud-proxy/src/config.ts +9 -3
  112. package/dist/templates/node-xmcloud-proxy/src/index.ts +54 -5
  113. package/dist/templates/node-xmcloud-proxy/src/types.ts +10 -42
  114. package/dist/templates/react/scripts/generate-config.js +10 -3
  115. package/dist/templates/vue/scripts/generate-config.js +5 -0
  116. package/package.json +2 -2
  117. package/dist/templates/angular/scripts/generate-component-factory.ts +0 -166
  118. package/dist/templates/angular/src/app/lib/graphql-client-factory.ts +0 -28
  119. package/dist/templates/angular-xmcloud/src/app/lib/graphql-client-factory.ts +0 -44
@@ -0,0 +1,67 @@
1
+ import { Component, OnInit, OnDestroy, ViewChild, TemplateRef } from '@angular/core';
2
+ import { Subscription } from 'rxjs';
3
+ import { EditMode, ImageField } from '@sitecore-jss/sitecore-jss-angular';
4
+ import { SxaComponent } from '../sxa.component';
5
+ import { JssContextService } from '../../jss-context.service';
6
+
7
+ @Component({
8
+ selector: 'app-image',
9
+ templateUrl: './image.component.html',
10
+ })
11
+ export class ImageComponent extends SxaComponent implements OnInit, OnDestroy {
12
+ @ViewChild('default', { static: true }) defaultVariant: TemplateRef<any>;
13
+ @ViewChild('banner', { static: true }) bannerVariant: TemplateRef<any>;
14
+ classHeroBannerEmpty = '';
15
+ backgroundStyle = {};
16
+ modifyImageProps = {};
17
+ isEditing = false;
18
+ private contextSubscription: Subscription;
19
+
20
+ constructor(private jssContext: JssContextService) {
21
+ super();
22
+ }
23
+
24
+ ngOnInit() {
25
+ super.ngOnInit();
26
+
27
+ const imageField = this.rendering.fields?.Image as ImageField;
28
+ this.backgroundStyle = imageField?.value?.src && {
29
+ 'background-image': `url('${imageField.value.src}')`,
30
+ };
31
+
32
+ this.contextSubscription = this.jssContext.state.subscribe((newState) => {
33
+ this.isEditing = newState.sitecore && newState.sitecore.context.pageEditing;
34
+
35
+ this.classHeroBannerEmpty =
36
+ this.isEditing && imageField?.value?.class === 'scEmptyImage' ? 'hero-banner-empty' : '';
37
+
38
+ const isMetadataMode = newState.sitecore?.context?.editMode === EditMode.Metadata;
39
+ this.modifyImageProps = !isMetadataMode
40
+ ? {
41
+ ...imageField,
42
+ editable: imageField?.editable
43
+ ?.replace(`width="${imageField?.value?.width}"`, 'width="100%"')
44
+ .replace(`height="${imageField?.value?.height}"`, 'height="100%"'),
45
+ }
46
+ : {
47
+ ...imageField,
48
+ value: {
49
+ ...imageField?.value,
50
+ style: { width: '100%', height: '100%' },
51
+ },
52
+ };
53
+ });
54
+ }
55
+
56
+ ngOnDestroy() {
57
+ if (this.contextSubscription) {
58
+ this.contextSubscription.unsubscribe();
59
+ }
60
+ }
61
+
62
+ public get variant(): TemplateRef<any> {
63
+ return this.rendering.params?.FieldNames === 'Banner'
64
+ ? this.bannerVariant
65
+ : this.defaultVariant;
66
+ }
67
+ }
@@ -0,0 +1,15 @@
1
+ <div class="component-content">
2
+ <ng-container *ngIf="title; else defaultTitle">
3
+ <h3 *scText="title"></h3>
4
+ </ng-container>
5
+ <ul>
6
+ <li *ngFor="let fieldLink of fieldLinks; index as i" [ngClass]="getFieldLinkClass(i)">
7
+ <div class="field-link">
8
+ <a *scGenericLink="fieldLink"></a>
9
+ </div>
10
+ </li>
11
+ </ul>
12
+ </div>
13
+ <ng-template #defaultTitle>
14
+ <span class="is-empty-hint">Link list</span>
15
+ </ng-template>
@@ -0,0 +1,41 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { SxaComponent } from '../sxa.component';
3
+ import { Field, LinkField, SxaLinkListFields } from '@sitecore-jss/sitecore-jss-angular';
4
+
5
+ @Component({
6
+ selector: 'app-link-list',
7
+ templateUrl: './link-list.component.html',
8
+ host: {
9
+ 'class': 'component link-list',
10
+ '[class]': 'styles',
11
+ '[attr.id]': 'id',
12
+ }
13
+ })
14
+ export class LinkListComponent extends SxaComponent<SxaLinkListFields> implements OnInit {
15
+ title?: Field<string>;
16
+ fieldLinks: LinkField[] = [];
17
+
18
+ getFieldLinkClass(index: number): string {
19
+ let className = `item${index}`;
20
+ className += (index + 1) % 2 == 0 ? ' even' : ' odd';
21
+ if (index === 0) {
22
+ className += ' first';
23
+ }
24
+ if (index + 1 === this.fieldLinks.length) {
25
+ className += ' last';
26
+ }
27
+ return className;
28
+ }
29
+
30
+ ngOnInit() {
31
+ super.ngOnInit();
32
+ const datasource = this.rendering.fields?.data?.datasource;
33
+ if (datasource) {
34
+ this.title = datasource.field?.title as Field<string>;
35
+ datasource.children.results.forEach(item => {
36
+ if (item.field?.link)
37
+ this.fieldLinks.push(item.field.link as LinkField);
38
+ });
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,23 @@
1
+ <li [class]="cssClasses" [ngClass]="{ active: isActive }" tabIndex="0">
2
+ <div [ngClass]="{ 'navigation-title': true, child: hasChildren }" (click)="isActive = !isActive">
3
+ <a *scRouterLink="linkField" (click)="onClick($event)">
4
+ <ng-container *ngIf="navItemFields.NavigationTitle"
5
+ ><span *scText="navItemFields.NavigationTitle"></span
6
+ ></ng-container>
7
+ <ng-container *ngIf="!navItemFields.NavigationTitle && navItemFields.Title">
8
+ <span *scText="navItemFields.Title"></span
9
+ ></ng-container>
10
+ <ng-container *ngIf="!navItemFields.NavigationTitle && !navItemFields.Title">{{
11
+ navItemFields.DisplayName
12
+ }}</ng-container>
13
+ </a>
14
+ </div>
15
+ <ul *ngIf="hasChildren" class="clearfix">
16
+ <app-navigation-item
17
+ *ngFor="let childNavItemFields of navItemFields.Children"
18
+ [navItemFields]="childNavItemFields"
19
+ [relativeLevel]="childrenRelativeLevel"
20
+ (childLinkClickEvent)="onClick($event)"
21
+ ></app-navigation-item>
22
+ </ul>
23
+ </li>
@@ -0,0 +1,65 @@
1
+ import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
2
+ import { LinkField } from '@sitecore-jss/sitecore-jss-angular';
3
+ import { Field } from '@sitecore-jss/sitecore-jss-angular';
4
+
5
+ export interface NavItemFields {
6
+ Id: string;
7
+ DisplayName: string;
8
+ Title: Field<string>;
9
+ NavigationTitle: Field<string>;
10
+ Href: string;
11
+ Querystring: string;
12
+ Children: Array<NavItemFields>;
13
+ Styles: string[];
14
+ }
15
+
16
+ @Component({
17
+ selector: 'app-navigation-item',
18
+ templateUrl: './navigation-item.component.html',
19
+ })
20
+ export class NavigationItemComponent implements OnInit {
21
+ @Input() navItemFields: NavItemFields;
22
+ @Input() relativeLevel: number;
23
+ @Output() childLinkClickEvent: EventEmitter<Event> = new EventEmitter<Event>();
24
+ cssClasses = '';
25
+ isActive = false;
26
+ linkField = {};
27
+ childrenRelativeLevel = 0;
28
+ hasChildren = false;
29
+
30
+ constructor() {}
31
+
32
+ ngOnInit() {
33
+ this.cssClasses = `${this.navItemFields.Styles.concat('rel-level' + this.relativeLevel).join(
34
+ ' '
35
+ )}`;
36
+ this.linkField = this.getLinkField(this.navItemFields);
37
+ this.hasChildren = this.navItemFields.Children && this.navItemFields.Children.length != 0;
38
+ this.childrenRelativeLevel = this.relativeLevel + 1;
39
+ }
40
+
41
+ onClick(event: Event) {
42
+ this.childLinkClickEvent.emit(event);
43
+ }
44
+
45
+ private getLinkField = (navItemFields: NavItemFields): LinkField => ({
46
+ value: {
47
+ href: navItemFields.Href,
48
+ title: this.getLinkTitle(navItemFields),
49
+ querystring: navItemFields.Querystring,
50
+ },
51
+ });
52
+
53
+ private getLinkTitle = (navItemFields: NavItemFields): string | undefined => {
54
+ let title;
55
+ if (navItemFields.NavigationTitle?.value) {
56
+ title = navItemFields.NavigationTitle.value.toString();
57
+ } else if (navItemFields.Title?.value) {
58
+ title = navItemFields.Title.value.toString();
59
+ } else {
60
+ title = navItemFields.DisplayName;
61
+ }
62
+
63
+ return title;
64
+ };
65
+ }
@@ -0,0 +1,21 @@
1
+ <label class="menu-mobile-navigate-wrapper">
2
+ <input
3
+ type="checkbox"
4
+ class="menu-mobile-navigate"
5
+ [checked]="isOpenMenu"
6
+ (change)="toggleMenu($event)"
7
+ />
8
+ <div class="menu-humburger"></div>
9
+ <div class="component-content">
10
+ <nav>
11
+ <ul class="clearfix">
12
+ <app-navigation-item
13
+ *ngFor="let navItemFields of rendering.fields"
14
+ [navItemFields]="navItemFields"
15
+ [relativeLevel]="baseLevel"
16
+ (childLinkClickEvent)="toggleMenu($event, false)"
17
+ ></app-navigation-item>
18
+ </ul>
19
+ </nav>
20
+ </div>
21
+ </label>
@@ -0,0 +1,49 @@
1
+ import { Component, OnInit, OnDestroy } from '@angular/core';
2
+ import { Subscription } from 'rxjs';
3
+ import { SxaComponent } from '../sxa.component';
4
+ import { JssContextService } from '../../jss-context.service';
5
+
6
+ @Component({
7
+ selector: 'app-navigation',
8
+ templateUrl: './navigation.component.html',
9
+ host: {
10
+ 'class': 'component navigation',
11
+ '[id]': 'id',
12
+ '[class]': 'styles + " " + rendering.params?.GridParameters',
13
+ },
14
+ })
15
+ export class NavigationComponent extends SxaComponent implements OnInit, OnDestroy {
16
+ isEditing = false;
17
+ private contextSubscription: Subscription;
18
+ isOpenMenu = false;
19
+ baseLevel = 1;
20
+
21
+ constructor(private jssContext: JssContextService) {
22
+ super();
23
+ }
24
+
25
+ ngOnInit() {
26
+ super.ngOnInit();
27
+ this.contextSubscription = this.jssContext.state.subscribe((newState) => {
28
+ this.isEditing = newState.sitecore && newState.sitecore.context.pageEditing;
29
+ });
30
+ }
31
+
32
+ ngOnDestroy() {
33
+ if (this.contextSubscription) {
34
+ this.contextSubscription.unsubscribe();
35
+ }
36
+ }
37
+
38
+ toggleMenu(event: Event, flag?: boolean) {
39
+ if (event && this.isEditing) {
40
+ event.preventDefault();
41
+ }
42
+
43
+ if (flag !== undefined) {
44
+ this.isOpenMenu = flag;
45
+ }
46
+
47
+ this.isOpenMenu = !this.isOpenMenu;
48
+ }
49
+ }
@@ -0,0 +1,5 @@
1
+ <div class="component-content">
2
+ <div class="field-content">
3
+ <div *scRichText="content || contextContent"></div>
4
+ </div>
5
+ </div>
@@ -0,0 +1,39 @@
1
+ import { Component, OnDestroy, OnInit } from '@angular/core';
2
+ import { RichTextField } from '@sitecore-jss/sitecore-jss-angular';
3
+ import { JssContextService } from '../../jss-context.service';
4
+ import { SxaComponent } from './../sxa.component';
5
+ import { Subscription } from 'rxjs';
6
+
7
+ @Component({
8
+ selector: 'app-page-content',
9
+ templateUrl: './page-content.component.html',
10
+ host: {
11
+ 'class': 'component content',
12
+ '[class]': 'styles',
13
+ '[id]': 'id',
14
+ }
15
+ })
16
+ export class PageContentComponent extends SxaComponent implements OnInit, OnDestroy {
17
+ content?: RichTextField;
18
+ contextContent?: RichTextField;
19
+ private contextSubscription: Subscription;
20
+
21
+ constructor(private jssContext: JssContextService) {
22
+ super();
23
+ }
24
+ ngOnInit() {
25
+ super.ngOnInit();
26
+
27
+ this.content = this.rendering.fields?.Content as RichTextField;
28
+ this.contextSubscription = this.jssContext.state.subscribe((newState) => {
29
+ this.contextContent =
30
+ newState.sitecore && (newState.sitecore.route.fields.Content as RichTextField);
31
+ });
32
+ }
33
+
34
+ ngOnDestroy() {
35
+ if (this.contextSubscription) {
36
+ this.contextSubscription.unsubscribe();
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,15 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { SxaComponent } from '../sxa.component';
3
+
4
+ @Component({
5
+ selector: 'app-partial-design-dynamic-placeholder',
6
+ templateUrl: './partial-design-dynamic-placeholder.component.html',
7
+ })
8
+ export class PartialDesignDynamicPlaceholderComponent extends SxaComponent implements OnInit {
9
+ sig: string;
10
+ ngOnInit() {
11
+ super.ngOnInit();
12
+
13
+ this.sig = this.rendering.params?.sig || '';
14
+ }
15
+ }
@@ -0,0 +1,21 @@
1
+ <div class="component-content">
2
+ <ng-container *ngIf="rendering.fields; else empty">
3
+ <div class="field-promoicon">
4
+ <img *scImage="rendering.fields.PromoIcon" />
5
+ </div>
6
+ <div class="promo-text">
7
+ <div>
8
+ <div class="field-promotext">
9
+ <div *scRichText="rendering.fields.PromoText"></div>
10
+ </div>
11
+ </div>
12
+ <div class="field-promolink">
13
+ <a *scGenericLink="rendering.fields.PromoLink"></a>
14
+ </div>
15
+ </div>
16
+ </ng-container>
17
+ </div>
18
+
19
+ <ng-template #empty>
20
+ <span className="is-empty-hint">Promo</span>
21
+ </ng-template>
@@ -0,0 +1,13 @@
1
+ import { Component } from '@angular/core';
2
+ import { SxaComponent } from '../sxa.component';
3
+
4
+ @Component({
5
+ selector: 'app-promo',
6
+ templateUrl: './promo.component.html',
7
+ host: {
8
+ 'class': 'component promo',
9
+ '[class]': "styles",
10
+ '[id]': "id",
11
+ },
12
+ })
13
+ export class PromoComponent extends SxaComponent {}
@@ -1,13 +1,8 @@
1
- <div
2
- class="component rich-text {{ styles }}"
3
- [attr.id]="id"
4
- >
5
- <div class="component-content">
6
- <ng-container *ngIf="text; else emptyHint">
7
- <div *scRichText="text"></div>
8
- </ng-container>
9
- <ng-template #emptyHint>
10
- <span class="is-empty-hint">Rich text</span>
11
- </ng-template>
12
- </div>
1
+ <div class="component-content">
2
+ <ng-container *ngIf="text; else emptyHint">
3
+ <div *scRichText="text"></div>
4
+ </ng-container>
5
+ <ng-template #emptyHint>
6
+ <span class="is-empty-hint">Rich text</span>
7
+ </ng-template>
13
8
  </div>
@@ -1,10 +1,15 @@
1
- import { Component, OnInit } from '@angular/core';
1
+ import { Component, OnInit } from '@angular/core';
2
2
  import { Field } from '@sitecore-jss/sitecore-jss-angular';
3
3
  import { SxaComponent } from '../sxa.component';
4
4
 
5
5
  @Component({
6
6
  selector: 'app-richtext',
7
7
  templateUrl: './richtext.component.html',
8
+ host: {
9
+ 'class': 'component rich-text',
10
+ '[class]': "styles",
11
+ "[attr.id]": "id"
12
+ },
8
13
  })
9
14
  export class RichTextComponent extends SxaComponent implements OnInit {
10
15
  text?: Field<string>;
@@ -0,0 +1,11 @@
1
+ <div
2
+ *ngFor="let ph of enabledPlaceholders"
3
+ class="container-fluid"
4
+ [ngClass]="getRowClass(+ph - 1)"
5
+ >
6
+ <div>
7
+ <div class="row">
8
+ <sc-placeholder [name]="getPlaceholderName(ph)" [rendering]="rendering"> </sc-placeholder>
9
+ </div>
10
+ </div>
11
+ </div>
@@ -0,0 +1,35 @@
1
+ import { Component } from '@angular/core';
2
+ import { SxaComponent } from '../sxa.component';
3
+
4
+ @Component({
5
+ selector: 'app-row-splitter',
6
+ templateUrl: './row-splitter.component.html',
7
+ host: {
8
+ "class": "component row-splitter",
9
+ "[class]": "rowSplitterStyles",
10
+ "[id]": "id"
11
+ }
12
+ })
13
+ export class RowSplitterComponent extends SxaComponent {
14
+ get rowSplitterStyles(): string {
15
+ return `${this.rendering.params.GridParameters ?? ''} ${this.rendering.params.Styles ??
16
+ ''}`.trimEnd();
17
+ }
18
+
19
+ get rowStyles(): string[] {
20
+ return Array.from({ length: 8 }, (_, i) => this.rendering.params[`Styles${i + 1}`]);
21
+ }
22
+
23
+ get enabledPlaceholders(): string[] {
24
+ return this.rendering.params.EnabledPlaceholders.split(',');
25
+ }
26
+
27
+ getRowClass(index: number): string {
28
+ const styleClass = this.rowStyles[index] || '';
29
+ return `${styleClass}`.trim();
30
+ }
31
+
32
+ getPlaceholderName(ph: string): string {
33
+ return `row-${ph}-{*}`;
34
+ }
35
+ }
@@ -1,9 +1,9 @@
1
1
  import { OnInit, Input, Directive } from '@angular/core';
2
- import { ComponentRendering } from '@sitecore-jss/sitecore-jss-angular';
2
+ import { ComponentFields, ComponentRendering } from '@sitecore-jss/sitecore-jss-angular';
3
3
 
4
4
  @Directive()
5
- export abstract class SxaComponent implements OnInit {
6
- @Input() rendering: ComponentRendering;
5
+ export abstract class SxaComponent<FieldType = ComponentFields> implements OnInit {
6
+ @Input() rendering: ComponentRendering<FieldType>;
7
7
 
8
8
  id?: string;
9
9
  styles?: string;
@@ -0,0 +1,10 @@
1
+ <div clas="component-content">
2
+ <div class="field-title">
3
+ <ng-container *ngIf="!pageEditing; else textOnly">
4
+ <a *scGenericLink="link"></a>
5
+ </ng-container>
6
+ </div>
7
+ </div>
8
+ <ng-template #textOnly>
9
+ <span *scText="text"></span>
10
+ </ng-template>
@@ -0,0 +1,56 @@
1
+ import { Component, OnDestroy, OnInit } from '@angular/core';
2
+ import { LinkField, SxaTitleFields, TextField } from '@sitecore-jss/sitecore-jss-angular';
3
+ import { SxaComponent } from '../sxa.component';
4
+ import { Subscription } from 'rxjs';
5
+ import { JssContextService } from '../../jss-context.service';
6
+
7
+ @Component({
8
+ selector: 'app-title',
9
+ templateUrl: './title.component.html',
10
+ host: {
11
+ 'class': 'component title',
12
+ '[class]': 'styles',
13
+ '[id]': 'id',
14
+ }
15
+ })
16
+ export class TitleComponent extends SxaComponent<SxaTitleFields> implements OnInit, OnDestroy {
17
+ text: TextField;
18
+ link: LinkField;
19
+ pageEditing?: boolean;
20
+
21
+ private contextSubscription: Subscription;
22
+
23
+ constructor(private jssContext: JssContextService) {
24
+ super();
25
+ }
26
+
27
+ ngOnInit() {
28
+ super.ngOnInit();
29
+ const datasource =
30
+ this.rendering.fields?.data?.datasource || this.rendering.fields?.data?.contextItem;
31
+ this.text = datasource.field?.jsonValue;
32
+ this.link = {
33
+ value: {
34
+ href: datasource?.url?.path,
35
+ title: datasource?.field?.jsonValue?.value,
36
+ text: datasource?.field?.jsonValue?.value,
37
+ },
38
+ };
39
+ this.contextSubscription = this.jssContext.state.subscribe(({ sitecore }) => {
40
+ this.pageEditing = sitecore.context.pageEditing;
41
+ if (sitecore.context.pageState !== 'normal') {
42
+ this.link.value.querystring = `sc_site=${datasource?.url?.siteName}`;
43
+ if (!this.text?.value) {
44
+ this.text.value = 'Title field';
45
+ this.link.value.href = '#';
46
+ }
47
+ }
48
+ });
49
+ }
50
+
51
+ ngOnDestroy() {
52
+ if (this.contextSubscription) {
53
+ this.contextSubscription.unsubscribe();
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,55 @@
1
+ import { Inject, Injectable } from '@angular/core';
2
+ import { DOCUMENT } from '@angular/common';
3
+ import { HTMLLink } from '@sitecore-jss/sitecore-jss-angular';
4
+
5
+ @Injectable({
6
+ providedIn: 'root',
7
+ })
8
+ export class JssLinkService {
9
+ constructor(@Inject(DOCUMENT) private document: Document) {}
10
+
11
+ /**
12
+ * Adds link element in the document head.
13
+ * @param headLinks - An array of HTMLLink objects to add to the head.
14
+ */
15
+ addHeadLinks(headLink: HTMLLink) {
16
+ if (!headLink) {
17
+ return;
18
+ }
19
+
20
+ // Check if a link with the same rel and href already exists
21
+ if (this.isDuplicateLink(headLink)) {
22
+ return;
23
+ }
24
+
25
+ this.createLink(headLink);
26
+ }
27
+
28
+ /**
29
+ * Creates a new link element and appends it to the head.
30
+ * @param headLink - An HTMLLink object to be added.
31
+ */
32
+ private createLink(headLink: HTMLLink) {
33
+ if (!headLink.rel || !headLink.href) {
34
+ console.log('Invalid link object:', headLink);
35
+ return;
36
+ }
37
+
38
+ const link: HTMLLinkElement = this.document.createElement('link');
39
+ link.setAttribute('rel', headLink.rel);
40
+ link.setAttribute('href', headLink.href);
41
+ this.document.head.appendChild(link);
42
+ }
43
+
44
+ /**
45
+ * Checks for an existing link element with the same rel and href attributes.
46
+ * @param headLink - An HTMLLink object to be checked.
47
+ * @returns {boolean} - True if a matching link exists, false otherwise.
48
+ */
49
+ private isDuplicateLink(headLink: HTMLLink): boolean {
50
+ const existingLink = this.document.head.querySelector(
51
+ `link[rel='${headLink.rel}'][href='${headLink.href}']`
52
+ );
53
+ return !!existingLink;
54
+ }
55
+ }
@@ -12,4 +12,6 @@ export interface JssConfig extends Record<string, string | boolean | undefined>
12
12
  defaultServerRoute?: string;
13
13
  proxyBuildPath?: string;
14
14
  proxyHost?: string;
15
+ sitecoreEdgeUrl?: string;
16
+ sitecoreEdgeContextId?: string;
15
17
  }