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,58 @@
1
+ import {
2
+ GraphQLRequestClientFactoryConfig,
3
+ getEdgeProxyContentUrl,
4
+ } from '@sitecore-jss/sitecore-jss-angular/cjs';
5
+ import { environment as env } from '../../../environments/environment';
6
+
7
+ /**
8
+ * Gets the configuration for the GraphQLRequestClientFactory
9
+ * @returns GraphQLRequestClientFactoryConfig
10
+ */
11
+ export const getGraphQLClientFactoryConfig = () => {
12
+ let clientConfig: GraphQLRequestClientFactoryConfig;
13
+
14
+ // Server side requests should go directly to the Sitecore, browser requests should go through the proxy.
15
+ const isServer = typeof window === 'undefined';
16
+ // If we are in a production environment we are going to use Node XM Cloud proxy
17
+ const isProduction = env.production === 'true';
18
+
19
+ if (isProduction) {
20
+ if (!env.proxyHost) {
21
+ throw new Error('Please configure your proxyHost.');
22
+ }
23
+
24
+ if (env.sitecoreEdgeContextId) {
25
+ clientConfig = {
26
+ endpoint: isServer
27
+ ? getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.sitecoreEdgeUrl)
28
+ : getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.proxyHost),
29
+ };
30
+ } else if (env.graphQLEndpoint && env.sitecoreApiKey) {
31
+ const graphQLEndpointPath = new URL(env.graphQLEndpoint).pathname;
32
+
33
+ clientConfig = {
34
+ endpoint: isServer ? env.graphQLEndpoint : `${env.proxyHost}${graphQLEndpointPath}`,
35
+ apiKey: env.sitecoreApiKey,
36
+ };
37
+ }
38
+ } else {
39
+ if (env.sitecoreEdgeContextId) {
40
+ clientConfig = {
41
+ endpoint: getEdgeProxyContentUrl(env.sitecoreEdgeContextId, env.sitecoreEdgeUrl),
42
+ };
43
+ } else if (env.graphQLEndpoint && env.sitecoreApiKey) {
44
+ clientConfig = {
45
+ endpoint: env.graphQLEndpoint,
46
+ apiKey: env.sitecoreApiKey,
47
+ };
48
+ }
49
+ }
50
+
51
+ if (!clientConfig?.endpoint) {
52
+ throw new Error(
53
+ 'Please configure either your sitecoreEdgeContextId, or your graphQLEndpoint and sitecoreApiKey.'
54
+ );
55
+ }
56
+
57
+ return clientConfig;
58
+ };
@@ -0,0 +1,38 @@
1
+ <div class="{{ mainClassPageEditing }}">
2
+ <ng-container *ngIf="state === LayoutState.Layout">
3
+ <app-scripts></app-scripts>
4
+ <header>
5
+ <div id="header">
6
+ <sc-placeholder
7
+ name="headless-header"
8
+ [rendering]="route"
9
+ (loaded)="onPlaceholderLoaded($event)"
10
+ ></sc-placeholder>
11
+ </div>
12
+ </header>
13
+ <main>
14
+ <div id="content">
15
+ <sc-placeholder
16
+ name="headless-main"
17
+ [rendering]="route"
18
+ (loaded)="onPlaceholderLoaded($event)"
19
+ ></sc-placeholder>
20
+ </div>
21
+ </main>
22
+ <footer>
23
+ <div id="footer">
24
+ <sc-placeholder
25
+ name="headless-footer"
26
+ [rendering]="route"
27
+ (loaded)="onPlaceholderLoaded($event)"
28
+ ></sc-placeholder>
29
+ </div>
30
+ </footer>
31
+ </ng-container>
32
+
33
+ <app-not-found
34
+ *ngIf="state === LayoutState.NotFound"
35
+ [errorContextData]="errorContextData"
36
+ ></app-not-found>
37
+ <app-server-error *ngIf="state === LayoutState.Error"></app-server-error>
38
+ </div>
@@ -0,0 +1,104 @@
1
+ /* eslint-disable no-shadow, no-console */
2
+ import { Component, OnInit, OnDestroy } from '@angular/core';
3
+ import {
4
+ RouteData,
5
+ Field,
6
+ LayoutServiceContextData,
7
+ getContentStylesheetLink,
8
+ } from '@sitecore-jss/sitecore-jss-angular';
9
+ import { ActivatedRoute } from '@angular/router';
10
+ import { Subscription } from 'rxjs';
11
+ import { JssState } from '../../JssState';
12
+ import { JssMetaService } from '../../jss-meta.service';
13
+ import { JssLinkService } from '../../jss-link.service';
14
+ import { environment as env } from '../../../environments/environment';
15
+
16
+ enum LayoutState {
17
+ Layout,
18
+ NotFound,
19
+ Error,
20
+ }
21
+
22
+ interface RouteFields {
23
+ [name: string]: unknown;
24
+ pageTitle?: Field<string>;
25
+ }
26
+
27
+ @Component({
28
+ selector: 'app-layout',
29
+ templateUrl: './layout.component.html',
30
+ })
31
+ export class LayoutComponent implements OnInit, OnDestroy {
32
+ route: RouteData<RouteFields>;
33
+ state: LayoutState;
34
+ LayoutState = LayoutState;
35
+ subscription: Subscription;
36
+ errorContextData: LayoutServiceContextData;
37
+ mainClassPageEditing: string;
38
+
39
+ constructor(
40
+ private activatedRoute: ActivatedRoute,
41
+ private readonly meta: JssMetaService,
42
+ private linkService: JssLinkService
43
+ ) {}
44
+
45
+ ngOnInit() {
46
+ // route data is populated by the JssRouteResolver
47
+ this.subscription = this.activatedRoute.data.subscribe((data: { jssState: JssState }) => {
48
+ if (!data.jssState) {
49
+ this.state = LayoutState.NotFound;
50
+ return;
51
+ }
52
+
53
+ if (data.jssState.sitecore && data.jssState.sitecore.route) {
54
+ this.route = data.jssState.sitecore.route;
55
+ this.setMetadata(this.route.fields);
56
+ this.state = LayoutState.Layout;
57
+ this.mainClassPageEditing = data.jssState.sitecore.context.pageEditing
58
+ ? 'editing-mode'
59
+ : 'prod-mode';
60
+
61
+ const contentStyles = getContentStylesheetLink(
62
+ { sitecore: data.jssState.sitecore },
63
+ env.sitecoreEdgeContextId,
64
+ env.sitecoreEdgeUrl
65
+ );
66
+
67
+ if (contentStyles) {
68
+ this.linkService.addHeadLinks(contentStyles);
69
+ }
70
+ }
71
+
72
+ if (data.jssState.routeFetchError) {
73
+ if (
74
+ data.jssState.routeFetchError.status >= 400 &&
75
+ data.jssState.routeFetchError.status < 500
76
+ ) {
77
+ this.state = LayoutState.NotFound;
78
+ } else {
79
+ this.state = LayoutState.Error;
80
+ }
81
+
82
+ this.errorContextData =
83
+ data.jssState.routeFetchError.data && data.jssState.routeFetchError.data.sitecore;
84
+ }
85
+ });
86
+ }
87
+
88
+ ngOnDestroy() {
89
+ // important to unsubscribe when the component is destroyed
90
+ this.subscription.unsubscribe();
91
+ }
92
+
93
+ setMetadata(routeFields: RouteFields) {
94
+ // set page title, if it exists
95
+ if (routeFields && routeFields.pageTitle) {
96
+ this.meta.setTitle(routeFields.pageTitle.value || 'Page');
97
+ }
98
+ }
99
+
100
+ onPlaceholderLoaded(_placeholderName: string) {
101
+ // you may optionally hook to the loaded event for a placeholder,
102
+ // which can be useful for analytics and other DOM-based things that need to know when a placeholder's content is available.
103
+ }
104
+ }
@@ -0,0 +1,77 @@
1
+ import { Component, OnInit, OnDestroy } from '@angular/core';
2
+ import { Subscription } from 'rxjs';
3
+ import { isServer, CdpHelper, LayoutServicePageState } from '@sitecore-jss/sitecore-jss-angular';
4
+ import { pageView, PageViewData } from '@sitecore-cloudsdk/events/browser';
5
+ import { JssContextService } from '../../jss-context.service';
6
+ import { JssState } from '../../JssState';
7
+ import { environment } from '../../../environments/environment';
8
+
9
+ /**
10
+ * This is the CDP page view component.
11
+ * It uses the Sitecore Cloud SDK to enable page view events on the client-side.
12
+ * See Sitecore Cloud SDK documentation for details.
13
+ * https://www.npmjs.com/package/@sitecore-cloudsdk/events
14
+ */
15
+ @Component({
16
+ selector: 'app-cdp-page-view',
17
+ template: '',
18
+ })
19
+ export class CdpPageViewComponent implements OnInit, OnDestroy {
20
+ private contextSubscription: Subscription;
21
+
22
+ constructor(private jssContext: JssContextService) {}
23
+
24
+ ngOnInit(): void {
25
+ if (!isServer()) {
26
+ this.contextSubscription = this.jssContext.state.subscribe((newState: JssState) => {
27
+ const {
28
+ route,
29
+ context: { pageState, language, variantId },
30
+ } = newState.sitecore;
31
+
32
+ // Do not create events in editing or preview mode or if missing route data
33
+ if (pageState !== LayoutServicePageState.Normal || !route?.itemId) {
34
+ return;
35
+ }
36
+
37
+ // Do not create events if disabled (e.g. we don't have consent)
38
+ if (this.disabled()) {
39
+ return;
40
+ }
41
+
42
+ const scope = process.env.PERSONALIZE_SCOPE;
43
+ const pageVariantId = CdpHelper.getPageVariantId(
44
+ route.itemId,
45
+ language || environment.defaultLanguage,
46
+ variantId as string,
47
+ scope
48
+ );
49
+
50
+ const pageViewData: PageViewData = {
51
+ channel: 'WEB',
52
+ currency: 'USD',
53
+ page: route.name,
54
+ pageVariantId,
55
+ language,
56
+ };
57
+
58
+ pageView(pageViewData).catch((err) => console.debug(err));
59
+ });
60
+ }
61
+ }
62
+
63
+ ngOnDestroy() {
64
+ if (this.contextSubscription) {
65
+ this.contextSubscription.unsubscribe();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Determines if the page view events should be turned off.
71
+ * IMPORTANT: You should implement based on your cookie consent management solution of choice.
72
+ * By default it is disabled if not in production mode
73
+ */
74
+ disabled = () => {
75
+ return !environment.production;
76
+ };
77
+ }
@@ -0,0 +1,48 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { take } from 'rxjs/operators';
3
+ import { CloudSDK } from '@sitecore-cloudsdk/core/browser';
4
+ import '@sitecore-cloudsdk/events/browser';
5
+ import { isServer, LayoutServicePageState } from '@sitecore-jss/sitecore-jss-angular';
6
+ import { environment } from '../../../environments/environment';
7
+ import { JssContextService } from '../../jss-context.service';
8
+ import { JssState } from '../../JssState';
9
+
10
+ /**
11
+ * Component to init CloudSDK logic - to allow events throughout the site
12
+ */
13
+ @Component({
14
+ selector: 'app-cloud-sdk-init',
15
+ template: '',
16
+ })
17
+ export class CloudSdkInitComponent implements OnInit {
18
+ constructor(private jssContext: JssContextService) {}
19
+
20
+ ngOnInit(): void {
21
+ if (!isServer() && environment.production) {
22
+ // to ensure that CloudSDK initialization logic runs only once in the browser, take only the first emitted value of state
23
+ this.jssContext.state.pipe(take(1)).subscribe((newState: JssState) => {
24
+ const {
25
+ route,
26
+ context: { pageState },
27
+ } = newState.sitecore;
28
+
29
+ // Do not initialize CloudSDK in editing or preview mode or if missing route data
30
+ if (pageState !== LayoutServicePageState.Normal || !route?.itemId) {
31
+ return;
32
+ }
33
+
34
+ CloudSDK({
35
+ siteName: environment.sitecoreSiteName,
36
+ sitecoreEdgeUrl: environment.sitecoreEdgeUrl,
37
+ sitecoreEdgeContextId: environment.sitecoreEdgeContextId,
38
+ // Replace with the top level cookie domain of the website that is being integrated e.g ".example.com" and not "www.example.com"
39
+ cookieDomain: window.location.hostname.replace(/^www\./, ''),
40
+ // Cookie may be created in personalize middleware (server), but if not we should create it here
41
+ enableBrowserCookie: true,
42
+ })
43
+ .addEvents()
44
+ .initialize();
45
+ });
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ <ng-container>
2
+ <sc-editing-scripts></sc-editing-scripts>
3
+ <app-cloud-sdk-init></app-cloud-sdk-init>
4
+ <app-cdp-page-view></app-cdp-page-view>
5
+ </ng-container>
@@ -0,0 +1,12 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { ScriptsComponent } from './scripts.component';
3
+ import { JssModule } from '@sitecore-jss/sitecore-jss-angular';
4
+ import { CloudSdkInitComponent } from './cloud-sdk-init.component';
5
+ import { CdpPageViewComponent } from './cdp-page-view.component';
6
+
7
+ @NgModule({
8
+ exports: [ScriptsComponent],
9
+ imports: [JssModule],
10
+ declarations: [ScriptsComponent, CloudSdkInitComponent, CdpPageViewComponent],
11
+ })
12
+ export class ScriptsModule {}
@@ -8,7 +8,9 @@
8
8
 
9
9
  @include respond-to(mobile-large) {
10
10
  padding-bottom: 0;
11
- flex-direction: column-reverse;
11
+ sc-placeholder {
12
+ flex-direction: column-reverse;
13
+ }
12
14
  }
13
15
  }
14
16
  }
@@ -2,3 +2,13 @@
2
2
  @import "bootstrap/scss/bootstrap";
3
3
  @import "sass/main.scss";
4
4
  @import "basic/main.scss";
5
+
6
+ sc-placeholder {
7
+ display: flex;
8
+ flex-direction: column;
9
+ flex-grow: 1;
10
+
11
+ &.row {
12
+ flex-direction: row;
13
+ }
14
+ }
@@ -9,7 +9,7 @@
9
9
  display: inline-block;
10
10
  max-width: 100%;
11
11
  }
12
- .image-caption {
12
+ span {
13
13
  display: block;
14
14
  font-style: italic;
15
15
  font-size: $font-small;
@@ -28,7 +28,7 @@
28
28
  "@sitecore-jss/sitecore-jss-nextjs": "~22.2.0-canary",
29
29
  "graphql": "~15.8.0",
30
30
  "graphql-tag": "^2.12.6",
31
- "next": "^14.1.0",
31
+ "next": "^14.2.7",
32
32
  "next-localization": "^0.12.0",
33
33
  "react": "^18.2.0",
34
34
  "react-dom": "^18.2.0",
@@ -13,7 +13,6 @@ class FallbackPlugin implements ConfigPlugin {
13
13
  async exec(config: JssConfig) {
14
14
  return Object.assign({}, config, {
15
15
  defaultLanguage: config.defaultLanguage || 'en',
16
- sitecoreApiKey: config.sitecoreApiKey || 'no-api-key-set',
17
16
  layoutServiceConfigurationName: config.layoutServiceConfigurationName || 'default',
18
17
  publicUrl: config.publicUrl || getPublicUrl(),
19
18
  });
@@ -29,6 +29,11 @@ generateConfig(defaultConfig);
29
29
  * @param {JssConfig} defaultConfig Default configuration.
30
30
  */
31
31
  function generateConfig(defaultConfig: JssConfig): void {
32
+ // Handle undefined values
33
+ Object.keys(defaultConfig).forEach(prop => {
34
+ defaultConfig[prop] = defaultConfig[prop] || '';
35
+ }, {});
36
+
32
37
  jssConfigFactory
33
38
  .create(defaultConfig)
34
39
  .then(config => {
@@ -53,7 +58,9 @@ const config = {};\n`;
53
58
 
54
59
  // Set configuration values, allowing override with environment variables
55
60
  Object.keys(config).forEach(prop => {
56
- configText += `config.${prop} = process.env.${constantCase(prop)} || '${config[prop]?.trim()}';\n`;
61
+ // Handle undefined values
62
+ const value = config[prop] || '';
63
+ configText += `config.${prop} = process.env.${constantCase(prop)} || '${value.trim()}';\n`;
57
64
  });
58
65
 
59
66
  configText += `module.exports = config;`;
@@ -7,7 +7,8 @@ import { Plugin, isServerSidePropsContext } from '..';
7
7
  class ComponentPropsPlugin implements Plugin {
8
8
  private componentPropsService: ComponentPropsService;
9
9
 
10
- order = 2;
10
+ // Make sure to run this plugin last to ensure that the updated layout data is used
11
+ order = 10;
11
12
 
12
13
  constructor() {
13
14
  this.componentPropsService = new ComponentPropsService();
@@ -29,6 +29,7 @@ class DisconnectedPlugin implements ConfigPlugin {
29
29
 
30
30
  return Object.assign({}, config, {
31
31
  sitecoreApiHost: `http://localhost:${port}`,
32
+ sitecoreApiKey: config.sitecoreApiKey || 'no-api-key-set',
32
33
  });
33
34
  }
34
35
  }
@@ -9,7 +9,7 @@
9
9
  display: inline-block;
10
10
  max-width: 100%;
11
11
  }
12
- .image-caption {
12
+ span {
13
13
  display: block;
14
14
  font-style: italic;
15
15
  font-size: $font-small;
@@ -1,26 +1,53 @@
1
+ @import '~bootstrap/scss/functions';
2
+ @import '~bootstrap/scss/variables';
3
+ @import '~bootstrap/scss/mixins';
4
+
5
+ $breakpoints: sm, md, lg, xl, xxl;
6
+
1
7
  .position-left,
2
8
  .position-left * {
3
- text-align: left !important;
9
+ text-align: left !important;
4
10
  }
5
11
 
6
12
  .position-right,
7
13
  .position-right * {
8
- text-align: right !important;
14
+ text-align: right !important;
9
15
  }
10
16
 
11
17
  .position-center,
12
18
  .position-center * {
13
- text-align: center !important;
19
+ text-align: center !important;
14
20
  }
15
21
 
16
22
  .position-left select {
17
- direction: ltr !important;
23
+ direction: ltr !important;
18
24
  }
19
25
 
20
26
  .position-right select {
21
- direction: rtl !important;
27
+ direction: rtl !important;
22
28
  }
23
29
 
24
30
  .position-center select {
25
- text-align-last: center !important;
26
- }
31
+ text-align-last: center !important;
32
+ }
33
+
34
+ @mixin auto-margins($breakpoint) {
35
+ @include media-breakpoint-up(#{$breakpoint}) {
36
+ .ms-#{$breakpoint}-auto {
37
+ margin-left: auto !important;
38
+ margin-right: 0 !important;
39
+ }
40
+ .me-#{$breakpoint}-auto {
41
+ margin-right: auto !important;
42
+ margin-left: 0 !important;
43
+ }
44
+ .mx-#{$breakpoint}-auto {
45
+ margin-right: auto !important;
46
+ margin-left: auto !important;
47
+ }
48
+ }
49
+ }
50
+
51
+ @each $breakpoint in $breakpoints {
52
+ @include auto-margins($breakpoint);
53
+ }
@@ -1,14 +1,9 @@
1
- import React from 'react';
2
1
  import {
3
2
  ComponentParams,
4
3
  ComponentRendering,
5
4
  Placeholder,
6
- useSitecoreContext,
7
5
  } from '@sitecore-jss/sitecore-jss-nextjs';
8
-
9
- const BACKGROUND_REG_EXP = new RegExp(
10
- /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/gi
11
- );
6
+ import React from 'react';
12
7
 
13
8
  interface ComponentProps {
14
9
  rendering: ComponentRendering & { params: ComponentParams };
@@ -16,22 +11,19 @@ interface ComponentProps {
16
11
  }
17
12
 
18
13
  const DefaultContainer = (props: ComponentProps): JSX.Element => {
19
- const { sitecoreContext } = useSitecoreContext();
20
14
  const containerStyles = props.params && props.params.Styles ? props.params.Styles : '';
21
15
  const styles = `${props.params.GridParameters} ${containerStyles}`.trimEnd();
22
16
  const phKey = `container-${props.params.DynamicPlaceholderId}`;
23
17
  const id = props.params.RenderingIdentifier;
18
+ const mediaUrlPattern = new RegExp(/mediaurl=\"([^"]*)\"/, 'i');
24
19
  let backgroundImage = props.params.BackgroundImage as string;
25
20
  let backgroundStyle: { [key: string]: string } = {};
26
21
 
27
- if (backgroundImage) {
28
- const prefix = `${sitecoreContext.pageState !== 'normal' ? '/sitecore/shell' : ''}/-/media/`;
29
- backgroundImage = `${backgroundImage
30
- ?.match(BACKGROUND_REG_EXP)
31
- ?.pop()
32
- ?.replace(/-/gi, '')}`;
22
+ if (backgroundImage && backgroundImage.match(mediaUrlPattern)) {
23
+ const mediaUrl = backgroundImage.match(mediaUrlPattern)?.[1] || '';
24
+
33
25
  backgroundStyle = {
34
- backgroundImage: `url('${prefix}${backgroundImage}')`,
26
+ backgroundImage: `url('${mediaUrl}')`,
35
27
  };
36
28
  }
37
29
 
@@ -4,7 +4,8 @@ import { Plugin } from '..';
4
4
  import config from 'temp/config';
5
5
 
6
6
  class ComponentThemesPlugin implements Plugin {
7
- order = 2;
7
+ // Make sure to run this plugin after the personalization plugin, since it relies on the layout data
8
+ order = 10;
8
9
 
9
10
  async exec(props: SitecorePageProps) {
10
11
  // Collect FEAAS, BYOC, SXA component themes
@@ -20,13 +20,14 @@ class PreviewModePlugin implements Plugin {
20
20
 
21
21
  // If we're in Pages preview (editing) Metadata Edit Mode, prefetch the editing data
22
22
  if (isEditingMetadataPreviewData(context.previewData)) {
23
- const { site, itemId, language, version, variantIds } = context.previewData;
23
+ const { site, itemId, language, version, variantIds, layoutKind } = context.previewData;
24
24
 
25
25
  const data = await graphQLEditingService.fetchEditingData({
26
26
  siteName: site,
27
27
  itemId,
28
28
  language,
29
29
  version,
30
+ layoutKind,
30
31
  });
31
32
 
32
33
  if (!data) {
@@ -0,0 +1,19 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+
6
+ # local env files
7
+ .env.local
8
+ .env.*.local
9
+
10
+ # IDE - VSCode
11
+ .vscode/*
12
+ !.vscode/settings.json
13
+ !.vscode/tasks.json
14
+ !.vscode/launch.json
15
+ !.vscode/extensions.json
16
+
17
+ # System Files
18
+ .DS_Store
19
+ Thumbs.db
@@ -0,0 +1,19 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+
6
+ # local env files
7
+ .env.local
8
+ .env.*.local
9
+
10
+ # IDE - VSCode
11
+ .vscode/*
12
+ !.vscode/settings.json
13
+ !.vscode/tasks.json
14
+ !.vscode/launch.json
15
+ !.vscode/extensions.json
16
+
17
+ # System Files
18
+ .DS_Store
19
+ Thumbs.db
@@ -1,4 +1,4 @@
1
- import { ProxyConfig, ServerBundle } from '@sitecore-jss/sitecore-jss-proxy';
1
+ import { headlessProxy } from '@sitecore-jss/sitecore-jss-proxy';
2
2
  import fs from 'fs';
3
3
  import { RestDictionaryService } from '@sitecore-jss/sitecore-jss/i18n';
4
4
  import { httpAgentsConfig } from './httpAgents';
@@ -13,7 +13,7 @@ let siteName = process.env.SITECORE_SITE_NAME || appName;
13
13
 
14
14
  const bundlePath = process.env.SITECORE_JSS_SERVER_BUNDLE || `../dist/${appName}/server.bundle`;
15
15
 
16
- const serverBundle = require(bundlePath) as ServerBundle;
16
+ const serverBundle = require(bundlePath) as headlessProxy.ServerBundle;
17
17
 
18
18
  httpAgentsConfig.setUpDefaultAgents(serverBundle);
19
19
 
@@ -33,7 +33,7 @@ const dictionaryService = new RestDictionaryService({
33
33
  /**
34
34
  * @type {ProxyConfig}
35
35
  */
36
- export const config: ProxyConfig = {
36
+ export const config: headlessProxy.ProxyConfig = {
37
37
  /**
38
38
  * The require'd server.bundle.js file from your pre-built JSS app
39
39
  */
@@ -1,4 +1,4 @@
1
- import { ServerBundle } from '@sitecore-jss/sitecore-jss-proxy';
1
+ import { headlessProxy } from '@sitecore-jss/sitecore-jss-proxy';
2
2
  import keepAlive from 'agentkeepalive';
3
3
  import http from 'http';
4
4
  import https from 'https';
@@ -14,7 +14,7 @@ const httpAgent = new keepAlive(keepAliveConfig);
14
14
  const httpsAgent = (new keepAlive.HttpsAgent(keepAliveConfig) as unknown) as https.Agent;
15
15
 
16
16
  interface HttpAgentsConfig {
17
- setUpDefaultAgents: (serverBundle: ServerBundle) => void;
17
+ setUpDefaultAgents: (serverBundle: headlessProxy.ServerBundle) => void;
18
18
  getAgent: (url: string) => http.Agent | https.Agent;
19
19
  }
20
20