create-sitecore-jss 20.0.0-canary.78

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 (166) hide show
  1. package/LICENSE.MD +202 -0
  2. package/dist/InitializerFactory.js +49 -0
  3. package/dist/common/Initializer.js +2 -0
  4. package/dist/common/args/base.js +2 -0
  5. package/dist/common/args/styleguide.js +2 -0
  6. package/dist/common/prompts/base.js +40 -0
  7. package/dist/common/prompts/styleguide.js +28 -0
  8. package/dist/common/steps/index.js +13 -0
  9. package/dist/common/steps/install.js +46 -0
  10. package/dist/common/steps/next.js +60 -0
  11. package/dist/common/steps/transform.js +185 -0
  12. package/dist/common/utils/cmd.js +39 -0
  13. package/dist/common/utils/helpers.js +92 -0
  14. package/dist/index.js +91 -0
  15. package/dist/init-runner.js +50 -0
  16. package/dist/initializers/nextjs/args.js +2 -0
  17. package/dist/initializers/nextjs/index.js +65 -0
  18. package/dist/initializers/nextjs/prompts.js +19 -0
  19. package/dist/initializers/nextjs/remove-dev-dependencies.js +24 -0
  20. package/dist/initializers/nextjs-styleguide/index.js +49 -0
  21. package/dist/templates/nextjs/.env +49 -0
  22. package/dist/templates/nextjs/.eslintrc +25 -0
  23. package/dist/templates/nextjs/.gitattributes +11 -0
  24. package/dist/templates/nextjs/.gitignore +33 -0
  25. package/dist/templates/nextjs/.graphql-let.yml +10 -0
  26. package/dist/templates/nextjs/.prettierignore +1 -0
  27. package/dist/templates/nextjs/.prettierrc +8 -0
  28. package/dist/templates/nextjs/LICENSE.txt +202 -0
  29. package/dist/templates/nextjs/README.md +3 -0
  30. package/dist/templates/nextjs/next-env.d.ts +6 -0
  31. package/dist/templates/nextjs/next.config.js +56 -0
  32. package/dist/templates/nextjs/package.json +88 -0
  33. package/dist/templates/nextjs/public/favicon.ico +0 -0
  34. package/dist/templates/nextjs/public/sc_logo.svg +20 -0
  35. package/dist/templates/nextjs/scripts/bootstrap.ts +40 -0
  36. package/dist/templates/nextjs/scripts/fetch-graphql-introspection-data.ts +49 -0
  37. package/dist/templates/nextjs/scripts/generate-component-factory.ts +95 -0
  38. package/dist/templates/nextjs/scripts/generate-config.ts +85 -0
  39. package/dist/templates/nextjs/scripts/generate-plugins.ts +103 -0
  40. package/dist/templates/nextjs/scripts/scaffold-component.ts +89 -0
  41. package/dist/templates/nextjs/scripts/templates/component-factory.ts +119 -0
  42. package/dist/templates/nextjs/scripts/templates/component-src.ts +27 -0
  43. package/dist/templates/nextjs/scripts/utils.ts +59 -0
  44. package/dist/templates/nextjs/sitecore/config/{{appName}}.config +151 -0
  45. package/dist/templates/nextjs/src/Layout.tsx +53 -0
  46. package/dist/templates/nextjs/src/Navigation.tsx +27 -0
  47. package/dist/templates/nextjs/src/NotFound.tsx +19 -0
  48. package/dist/templates/nextjs/src/assets/app.css +28 -0
  49. package/dist/templates/nextjs/src/components/ContentBlock.tsx +24 -0
  50. package/dist/templates/nextjs/src/lib/component-props/index.ts +23 -0
  51. package/dist/templates/nextjs/src/lib/data-fetcher.ts +16 -0
  52. package/dist/templates/nextjs/src/lib/dictionary-service-factory.ts +30 -0
  53. package/dist/templates/nextjs/src/lib/layout-service-factory.ts +25 -0
  54. package/dist/templates/nextjs/src/lib/next-config/plugins/graphql.js +32 -0
  55. package/dist/templates/nextjs/src/lib/next-config/plugins/monorepo.js +27 -0
  56. package/dist/templates/nextjs/src/lib/page-props-factory/index.ts +50 -0
  57. package/dist/templates/nextjs/src/lib/page-props-factory/plugins/componentProps.ts +38 -0
  58. package/dist/templates/nextjs/src/lib/page-props-factory/plugins/normalMode.ts +75 -0
  59. package/dist/templates/nextjs/src/lib/page-props-factory/plugins/previewMode.ts +27 -0
  60. package/dist/templates/nextjs/src/lib/page-props.ts +16 -0
  61. package/dist/templates/nextjs/src/lib/sitemap-fetcher/index.ts +25 -0
  62. package/dist/templates/nextjs/src/lib/sitemap-fetcher/plugins/graphqlSitemapService.ts +36 -0
  63. package/dist/templates/nextjs/src/pages/404.tsx +5 -0
  64. package/dist/templates/nextjs/src/pages/[[...path]].tsx +91 -0
  65. package/dist/templates/nextjs/src/pages/_app.tsx +19 -0
  66. package/dist/templates/nextjs/src/pages/_error.tsx +35 -0
  67. package/dist/templates/nextjs/src/pages/api/editing/data/[key].ts +24 -0
  68. package/dist/templates/nextjs/src/pages/api/editing/render.ts +30 -0
  69. package/dist/templates/nextjs/src/temp/.gitignore +3 -0
  70. package/dist/templates/nextjs/src/temp/GraphQLIntrospectionResult.json +22216 -0
  71. package/dist/templates/nextjs/tsconfig.json +42 -0
  72. package/dist/templates/nextjs/tsconfig.scripts.json +6 -0
  73. package/dist/templates/nextjs-styleguide/data/component-content/.gitignore +0 -0
  74. package/dist/templates/nextjs-styleguide/data/component-content/Styleguide/ContentReuse/LoremIpsumContentBlock/en.yml +9 -0
  75. package/dist/templates/nextjs-styleguide/data/content/.gitignore +0 -0
  76. package/dist/templates/nextjs-styleguide/data/content/Styleguide/ContentListField/Item1/en.yml +6 -0
  77. package/dist/templates/nextjs-styleguide/data/content/Styleguide/ContentListField/Item2/en.yml +6 -0
  78. package/dist/templates/nextjs-styleguide/data/content/Styleguide/ItemLinkField/Item1/en.yml +6 -0
  79. package/dist/templates/nextjs-styleguide/data/content/Styleguide/ItemLinkField/Item2/en.yml +6 -0
  80. package/dist/templates/nextjs-styleguide/data/dictionary/en.yml +4 -0
  81. package/dist/templates/nextjs-styleguide/data/dictionary/{{language}}.yml +4 -0
  82. package/dist/templates/nextjs-styleguide/data/media/files/jss.pdf +0 -0
  83. package/dist/templates/nextjs-styleguide/data/media/img/jss_logo.png +0 -0
  84. package/dist/templates/nextjs-styleguide/data/media/img/sc_logo.png +0 -0
  85. package/dist/templates/nextjs-styleguide/data/routes/en.yml +63 -0
  86. package/dist/templates/nextjs-styleguide/data/routes/graphql/en.yml +27 -0
  87. package/dist/templates/nextjs-styleguide/data/routes/graphql/sample-1/en.yml +9 -0
  88. package/dist/templates/nextjs-styleguide/data/routes/graphql/sample-2/en.yml +9 -0
  89. package/dist/templates/nextjs-styleguide/data/routes/styleguide/custom-route-type/en.yml +12 -0
  90. package/dist/templates/nextjs-styleguide/data/routes/styleguide/en.yml +246 -0
  91. package/dist/templates/nextjs-styleguide/data/routes/styleguide/{{language}}.yml +25 -0
  92. package/dist/templates/nextjs-styleguide/data/routes/{{language}}.yml +4 -0
  93. package/dist/templates/nextjs-styleguide/package.json +13 -0
  94. package/dist/templates/nextjs-styleguide/scripts/disconnected-mode-proxy.ts +48 -0
  95. package/dist/templates/nextjs-styleguide/scripts/scaffold-component.ts +130 -0
  96. package/dist/templates/nextjs-styleguide/scripts/templates/component-manifest.ts +30 -0
  97. package/dist/templates/nextjs-styleguide/sitecore/definitions/component-content.sitecore.ts +117 -0
  98. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/ContentBlock.sitecore.ts +19 -0
  99. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Checkbox.sitecore.ts +23 -0
  100. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-ContentList.sitecore.ts +32 -0
  101. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Custom.sitecore.ts +23 -0
  102. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Date.sitecore.ts +23 -0
  103. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-File.sitecore.ts +20 -0
  104. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Image.sitecore.ts +23 -0
  105. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-ItemLink.sitecore.ts +32 -0
  106. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Link.sitecore.ts +25 -0
  107. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Number.sitecore.ts +20 -0
  108. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-RichText.sitecore.ts +28 -0
  109. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/fields/Styleguide-FieldUsage-Text.sitecore.ts +28 -0
  110. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/graphql/GraphQL-ConnectedDemo.sitecore.ts +18 -0
  111. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/graphql/GraphQL-IntegratedDemo.sitecore.graphql +71 -0
  112. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/graphql/GraphQL-IntegratedDemo.sitecore.ts +25 -0
  113. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/graphql/GraphQL-Layout.sitecore.ts +15 -0
  114. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-ComponentParams.sitecore.ts +20 -0
  115. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-CustomRouteType.sitecore.ts +31 -0
  116. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Layout-Reuse.sitecore.ts +20 -0
  117. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Layout-Tabs-Tab.sitecore.ts +23 -0
  118. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Layout-Tabs.sitecore.ts +20 -0
  119. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Layout.sitecore.ts +15 -0
  120. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Multilingual.sitecore.ts +26 -0
  121. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-RouteFields.sitecore.ts +22 -0
  122. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Section.sitecore.ts +16 -0
  123. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-SitecoreContext.sitecore.ts +19 -0
  124. package/dist/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-Tracking.sitecore.ts +19 -0
  125. package/dist/templates/nextjs-styleguide/sitecore/definitions/config.js +5 -0
  126. package/dist/templates/nextjs-styleguide/sitecore/definitions/content.sitecore.ts +117 -0
  127. package/dist/templates/nextjs-styleguide/sitecore/definitions/dictionary.sitecore.ts +52 -0
  128. package/dist/templates/nextjs-styleguide/sitecore/definitions/placeholders.sitecore.ts +21 -0
  129. package/dist/templates/nextjs-styleguide/sitecore/definitions/routes.sitecore.ts +88 -0
  130. package/dist/templates/nextjs-styleguide/sitecore/definitions/templates/Styleguide-ContentList-Template.sitecore.ts +12 -0
  131. package/dist/templates/nextjs-styleguide/sitecore/definitions/templates/Styleguide-Explanatory-Component.sitecore.ts +20 -0
  132. package/dist/templates/nextjs-styleguide/sitecore/definitions/templates/Styleguide-ItemLink-Template.sitecore.ts +13 -0
  133. package/dist/templates/nextjs-styleguide/src/Navigation.tsx +41 -0
  134. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Checkbox.tsx +52 -0
  135. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-ContentList.tsx +58 -0
  136. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Custom.tsx +25 -0
  137. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Date.tsx +55 -0
  138. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-File.tsx +30 -0
  139. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Image.tsx +58 -0
  140. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-ItemLink.tsx +50 -0
  141. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Link.tsx +46 -0
  142. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Number.tsx +34 -0
  143. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-RichText.tsx +35 -0
  144. package/dist/templates/nextjs-styleguide/src/components/fields/Styleguide-FieldUsage-Text.tsx +43 -0
  145. package/dist/templates/nextjs-styleguide/src/components/graphql/GraphQL-ConnectedDemo.dynamic.graphql +69 -0
  146. package/dist/templates/nextjs-styleguide/src/components/graphql/GraphQL-ConnectedDemo.dynamic.tsx +148 -0
  147. package/dist/templates/nextjs-styleguide/src/components/graphql/GraphQL-IntegratedDemo.tsx +130 -0
  148. package/dist/templates/nextjs-styleguide/src/components/graphql/GraphQL-Layout.tsx +37 -0
  149. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-ComponentParams.tsx +47 -0
  150. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-CustomRouteType.tsx +37 -0
  151. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Reuse.tsx +45 -0
  152. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs-Tab.tsx +41 -0
  153. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs.tsx +111 -0
  154. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout.tsx +68 -0
  155. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Multilingual.tsx +50 -0
  156. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-RouteFields.tsx +37 -0
  157. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Section.tsx +22 -0
  158. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-SitecoreContext.tsx +25 -0
  159. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Specimen.tsx +41 -0
  160. package/dist/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Tracking.tsx +341 -0
  161. package/dist/templates/nextjs-styleguide/src/lib/component-props/styleguide.ts +11 -0
  162. package/dist/templates/nextjs-styleguide/src/lib/next-config/plugins/disconnected.js +43 -0
  163. package/dist/templates/nextjs-styleguide/src/lib/next-config/plugins/styleguide.js +10 -0
  164. package/dist/templates/nextjs-styleguide/src/lib/sitemap-fetcher/plugins/disconnectedSitemapService.ts +46 -0
  165. package/dist/templates/nextjs-styleguide/src/pages/_app.tsx +33 -0
  166. package/package.json +61 -0
@@ -0,0 +1,148 @@
1
+ import React, { useEffect } from 'react';
2
+ import {
3
+ Text,
4
+ Link,
5
+ GetServerSideComponentProps,
6
+ GetStaticComponentProps,
7
+ useComponentProps,
8
+ constants,
9
+ GraphQLRequestClient,
10
+ withDatasourceCheck,
11
+ resetEditorChromes,
12
+ } from '@sitecore-jss/sitecore-jss-nextjs';
13
+ import NextLink from 'next/link';
14
+ import {
15
+ ConnectedDemoQueryDocument,
16
+ <%- appPrefix ? `${helper.getPascalCaseName(appName)}` : "" %>AppRoute as AppRoute,
17
+ Item,
18
+ <%- appPrefix ? `${helper.getPascalCaseName(appName)}` : "" %>GraphQlConnectedDemo as GrapQLConnectedDemoDatasource,
19
+ } from './GraphQL-ConnectedDemo.dynamic.graphql';
20
+ import { ComponentProps } from 'lib/component-props';
21
+ import config from 'temp/config';
22
+
23
+ type RouteItem = AppRoute & Item;
24
+
25
+ type GraphQLConnectedDemoData = {
26
+ datasource: GrapQLConnectedDemoDatasource;
27
+ contextItem: RouteItem;
28
+ };
29
+
30
+ const GraphQLConnectedDemo = (props: ComponentProps): JSX.Element => {
31
+ const data = useComponentProps<GraphQLConnectedDemoData>(props.rendering.uid);
32
+
33
+ useEffect(() => {
34
+ resetEditorChromes();
35
+ }, []);
36
+
37
+ return (
38
+ <div data-e2e-id="graphql-connected">
39
+ <h2>GraphQL Connected Demo</h2>
40
+
41
+ <p>
42
+ Connected GraphQL executes GraphQL queries directly against the Sitecore GraphQL endpoint.
43
+ This example runs the query server-side using component-level <code>getStaticProps</code>/
44
+ <code>getServerSideProps</code>, a feature of the Sitecore JSS Next.js SDK. These are
45
+ aggregated during the the Next.js page-level <code>getStaticProps</code>/
46
+ <code>getServerSideProps</code> execution.
47
+ </p>
48
+
49
+ {data && data.datasource && (
50
+ <div>
51
+ <h4>Datasource Item (via Connected GraphQL)</h4>
52
+ id: {data.datasource.id}
53
+ <br />
54
+ name: {data.datasource.name}
55
+ <br />
56
+ sample1: {data.datasource.sample1?.value}
57
+ <br />
58
+ sample1 (editable): <Text field={data.datasource.sample1?.jsonValue} />
59
+ <br />
60
+ sample2:
61
+ <br />
62
+ <ul>
63
+ <li>text: {data.datasource.sample2?.text}</li>
64
+ <li>url: {data.datasource.sample2?.url}</li>
65
+ <li>target: {data.datasource.sample2?.target}</li>
66
+ <li>
67
+ editable: <Link field={data.datasource.sample2?.jsonValue} />
68
+ </li>
69
+ <li>field type: {data.datasource.sample2?.definition?.type}</li>
70
+ <li>field is shared?: {data.datasource.sample2?.definition?.shared.toString()}</li>
71
+ </ul>
72
+ </div>
73
+ )}
74
+ {data && data.contextItem && (
75
+ <div>
76
+ <h4>Route Item (via Connected GraphQL)</h4>
77
+ id: {data.contextItem.id}
78
+ <br />
79
+ page title: {data.contextItem.pageTitle?.value}
80
+ <br />
81
+ children:
82
+ <ul>
83
+ {data.contextItem.children.results.map((child) => {
84
+ const routeItem = child as RouteItem;
85
+
86
+ return (
87
+ <li key={routeItem.id}>
88
+ <NextLink href={routeItem.url.path}>{routeItem.pageTitle?.value}</NextLink>
89
+ (editable title too! <Text field={routeItem.pageTitle?.jsonValue} />)
90
+ </li>
91
+ );
92
+ })}
93
+ </ul>
94
+ </div>
95
+ )}
96
+ </div>
97
+ );
98
+ };
99
+
100
+ /**
101
+ * Will be called during SSG
102
+ * @param {ComponentRendering} rendering
103
+ * @param {LayoutServiceData} layoutData
104
+ * @param {GetStaticPropsContext} context
105
+ */
106
+ export const getStaticProps: GetStaticComponentProps = async (rendering, layoutData) => {
107
+ if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
108
+ return null;
109
+ }
110
+
111
+ const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {
112
+ apiKey: config.sitecoreApiKey,
113
+ });
114
+
115
+ const result = await graphQLClient.request<GraphQLConnectedDemoData>(ConnectedDemoQueryDocument, {
116
+ datasource: rendering.dataSource,
117
+ contextItem: layoutData?.sitecore?.route?.itemId,
118
+ language: layoutData?.sitecore?.context?.language,
119
+ });
120
+
121
+ return result;
122
+ };
123
+
124
+ /**
125
+ * Will be called during SSR
126
+ * @param {ComponentRendering} rendering
127
+ * @param {LayoutServiceData} layoutData
128
+ * @param {GetServerSidePropsContext} context
129
+ */
130
+ export const getServerSideProps: GetServerSideComponentProps = async (rendering, layoutData) => {
131
+ if (process.env.JSS_MODE === constants.JSS_MODE.DISCONNECTED) {
132
+ return null;
133
+ }
134
+
135
+ const graphQLClient = new GraphQLRequestClient(config.graphQLEndpoint, {
136
+ apiKey: config.sitecoreApiKey,
137
+ });
138
+
139
+ const result = await graphQLClient.request<GraphQLConnectedDemoData>(ConnectedDemoQueryDocument, {
140
+ datasource: rendering.dataSource,
141
+ contextItem: layoutData?.sitecore?.route?.itemId,
142
+ language: layoutData?.sitecore?.context?.language,
143
+ });
144
+
145
+ return result;
146
+ };
147
+
148
+ export default withDatasourceCheck()<ComponentProps>(GraphQLConnectedDemo);
@@ -0,0 +1,130 @@
1
+ import { Text, Link, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs';
2
+ import { ComponentProps } from 'lib/component-props';
3
+ import NextLink from 'next/link';
4
+
5
+ type DataSource = {
6
+ sample1: {
7
+ jsonValue: {
8
+ value: string;
9
+ };
10
+ value: string;
11
+ };
12
+ sample2: {
13
+ definition: {
14
+ type: string;
15
+ shared: boolean;
16
+ };
17
+ jsonValue: {
18
+ value: {
19
+ href: string;
20
+ linktype: string;
21
+ target: string;
22
+ text: string;
23
+ url: string;
24
+ };
25
+ };
26
+ target: string;
27
+ text: string;
28
+ url: string;
29
+ };
30
+ name: string;
31
+ id: string;
32
+ };
33
+
34
+ type Item = {
35
+ id: string;
36
+ url: {
37
+ path: string;
38
+ };
39
+ pageTitle: {
40
+ value: string;
41
+ jsonValue: {
42
+ value: string;
43
+ };
44
+ };
45
+ };
46
+
47
+ type ItemSearchResults = {
48
+ results: Item[];
49
+ };
50
+
51
+ type GraphQlIntegratedDemoProps = ComponentProps & {
52
+ fields: {
53
+ data: {
54
+ datasource: DataSource;
55
+ contextItem: {
56
+ id: string;
57
+ children: ItemSearchResults;
58
+ pageTitle: {
59
+ value: string;
60
+ };
61
+ };
62
+ };
63
+ };
64
+ };
65
+
66
+ const GraphQLIntegratedDemo = (props: GraphQlIntegratedDemoProps): JSX.Element => {
67
+ // Query results in integrated GraphQL replace the normal `fields` data
68
+ // i.e. with { data, }
69
+ const { datasource, contextItem } = props.fields.data;
70
+
71
+ return (
72
+ <div data-e2e-id="graphql-integrated">
73
+ <h2>GraphQL Integrated Demo</h2>
74
+
75
+ <p>
76
+ Integrated GraphQL executes GraphQL queries within the Layout Service endpoint, and merges
77
+ the query results into the Layout Service result JSON. The query results can be seen by
78
+ inspecting the Layout Service response.
79
+ </p>
80
+
81
+ {datasource && (
82
+ <div>
83
+ <h4>Datasource Item (via Integrated GraphQL)</h4>
84
+ id: {datasource.id}
85
+ <br />
86
+ name: {datasource.name}
87
+ <br />
88
+ sample1: {datasource.sample1.value}
89
+ <br />
90
+ sample1 (editable): <Text field={datasource.sample1.jsonValue} />
91
+ <br />
92
+ sample2:
93
+ <br />
94
+ <ul>
95
+ <li>text: {datasource.sample2.text}</li>
96
+ <li>url: {datasource.sample2.url}</li>
97
+ <li>target: {datasource.sample2.target}</li>
98
+ <li>
99
+ editable: <Link field={datasource.sample2.jsonValue} />
100
+ </li>
101
+ <li>field type: {datasource.sample2.definition.type}</li>
102
+ <li>field is shared?: {datasource.sample2.definition.shared.toString()}</li>
103
+ </ul>
104
+ </div>
105
+ )}
106
+ {contextItem && (
107
+ <div>
108
+ <h4>Route Item (via Integrated GraphQL)</h4>
109
+ id: {contextItem.id}
110
+ <br />
111
+ page title: {contextItem.pageTitle.value}
112
+ <br />
113
+ children:
114
+ <ul>
115
+ {contextItem.children.results.map((child: Item) => (
116
+ <li key={child.id}>
117
+ <NextLink href={child.url.path}>
118
+ <a>{child.pageTitle.value}</a>
119
+ </NextLink>
120
+ &nbsp; (editable title too! <Text field={child.pageTitle.jsonValue} />)
121
+ </li>
122
+ ))}
123
+ </ul>
124
+ </div>
125
+ )}
126
+ </div>
127
+ );
128
+ };
129
+
130
+ export default withDatasourceCheck()<GraphQlIntegratedDemoProps>(GraphQLIntegratedDemo);
@@ -0,0 +1,37 @@
1
+ import { Placeholder, useSitecoreContext } from '@sitecore-jss/sitecore-jss-nextjs';
2
+ import { ComponentProps } from 'lib/component-props';
3
+
4
+ const GraphQLLayout = ({ rendering }: ComponentProps): JSX.Element => {
5
+ const { sitecoreContext } = useSitecoreContext();
6
+
7
+ const disconnectedMode =
8
+ sitecoreContext.route && sitecoreContext.route.layoutId === 'available-in-connected-mode';
9
+
10
+ return (
11
+ <div data-e2e-id="graphql-layout">
12
+ {disconnectedMode && (
13
+ <>
14
+ <p>
15
+ This app is running in disconnected mode. GraphQL requires connected mode, headless
16
+ connected mode, or integrated mode to work.
17
+ </p>
18
+ <p>
19
+ Libraries such as <code>graphql-tools</code> can provide GraphQL API mocking
20
+ capabilities, which could enable disconnected GraphQL. This is not supported out of the
21
+ box, however.
22
+ </p>
23
+ <p>
24
+ To view the GraphQL samples, restart the app using <code>jss start:connected</code>
25
+ &nbsp; or deploy the app to Sitecore to run in integrated mode per the JSS
26
+ documentation.
27
+ </p>
28
+ </>
29
+ )}
30
+ {!disconnectedMode && (
31
+ <Placeholder name="<%- helper.getAppPrefix(appPrefix, appName) %>jss-graphql-layout" rendering={rendering} />
32
+ )}
33
+ </div>
34
+ );
35
+ };
36
+
37
+ export default GraphQLLayout;
@@ -0,0 +1,47 @@
1
+ import StyleguideSpecimen from './Styleguide-Specimen';
2
+ import { ComponentProps } from 'lib/component-props';
3
+ import { StyleguideSpecimenFields } from 'lib/component-props/styleguide';
4
+
5
+ type StyleguideComponentParamsProps = ComponentProps &
6
+ StyleguideSpecimenFields & {
7
+ params: {
8
+ cssClass: string;
9
+ columns: string;
10
+ useCallToAction: 'false' | 'true';
11
+ };
12
+ };
13
+
14
+ const StyleguideComponentParams = (props: StyleguideComponentParamsProps): JSX.Element => {
15
+ // props.params (i.e. props.params.cssClass without destructuring) contains the component's params
16
+ const { cssClass, columns, useCallToAction } = props.params;
17
+
18
+ const columnsArray = columns && [...Array(parseInt(columns))];
19
+
20
+ return (
21
+ <StyleguideSpecimen {...props} e2eId="styleguide-componentparams">
22
+ <p className={cssClass}>
23
+ The CSS class of this paragraph (<code>{cssClass}</code>) is set using a param
24
+ </p>
25
+ <div>
26
+ {/* Note that all params come in as string values, like this boolean-like param here: */}
27
+ useCallToAction param: <code>{useCallToAction}</code>
28
+ <br />
29
+ param type: <code>{typeof useCallToAction}</code>
30
+ {useCallToAction === 'true' && (
31
+ <div className="alert alert-info">the call to action is shown</div>
32
+ )}
33
+ </div>
34
+ <p>columns param: {columns}</p>
35
+ <div className="row">
36
+ {columnsArray &&
37
+ columnsArray.map((_, index) => (
38
+ <div key={`col-${index}`} className="col-sm">
39
+ Column {index}
40
+ </div>
41
+ ))}
42
+ </div>
43
+ </StyleguideSpecimen>
44
+ );
45
+ };
46
+
47
+ export default StyleguideComponentParams;
@@ -0,0 +1,37 @@
1
+ import Link from 'next/link';
2
+ import { useSitecoreContext, Text, RichText, Field } from '@sitecore-jss/sitecore-jss-nextjs';
3
+
4
+ type StyleguideCustomRouteTypeFields = {
5
+ headline: Field<string>;
6
+ author: Field<string>;
7
+ content: Field<string>;
8
+ };
9
+
10
+ const StyleguideCustomRouteType = (): JSX.Element => {
11
+ // useSitecoreContext() is the magical glue that gives you route-level context access
12
+ // see the context examples in the styleguide for more details.
13
+ // this fancy destructure syntax is essentially equivalent to
14
+ // const fields = props.sitecoreContext.route.fields
15
+ const value = useSitecoreContext();
16
+ const fields = value.sitecoreContext.route?.fields as StyleguideCustomRouteTypeFields;
17
+
18
+ return (
19
+ <div data-e2e-id="styleguide-customroutetype">
20
+ <Text tag="h3" field={fields.headline} />
21
+
22
+ <p>
23
+ <em>
24
+ By <Text field={fields.author} />
25
+ </em>
26
+ </p>
27
+
28
+ <RichText field={fields.content} />
29
+
30
+ <Link href="/styleguide">
31
+ <a>Return to the Styleguide</a>
32
+ </Link>
33
+ </div>
34
+ );
35
+ };
36
+
37
+ export default StyleguideCustomRouteType;
@@ -0,0 +1,45 @@
1
+ import { Placeholder } from '@sitecore-jss/sitecore-jss-nextjs';
2
+ import StyleguideSpecimen from './Styleguide-Specimen';
3
+ import { ComponentProps } from 'lib/component-props';
4
+ import { StyleguideSpecimenFields } from 'lib/component-props/styleguide';
5
+
6
+ type StyleguideLayoutReuseProps = ComponentProps & StyleguideSpecimenFields;
7
+
8
+ /**
9
+ * Demonstrates how to reuse content within JSS. See /data/routes/styleguide/en.yml
10
+ * for the reused content definition sample. This component also demonstrates how to use
11
+ * the Placeholder component's render props API to wrap all components in the placeholder
12
+ * in a column tag (thus creating a horizontally laid out placeholder)
13
+ */
14
+ const StyleguideLayoutReuse = (props: StyleguideLayoutReuseProps): JSX.Element => (
15
+ <StyleguideSpecimen {...props} e2eId="styleguide-layout-reuse">
16
+ <div className="row">
17
+ {/*
18
+ This placeholder is using _render props_ to enable customizing the markup for each component within.
19
+ In this case, it's placing each component in its own column of a flexbox layout - giving an n-up columnar layout.
20
+ The component itself does not need to know it's living in a columnar layout.
21
+
22
+ There are three render props available:
23
+ renderEach - called once for each content component
24
+ Sitecore Experience Editor markup is automatically rendered in between content components when present
25
+ renderEmpty - called when the placeholder contains no content components. Can be used to wrap the Sitecore EE empty placeholder
26
+ markup in something that's visually correct, like here where we need to wrap it in a column div to make it selectable.
27
+ render - called once and passed _all_ components in the placeholder. Allows custom iteration. EE code markup must be accounted for.
28
+
29
+ Generally speaking stick to renderEach and renderEmpty unless doing something really custom.
30
+ */}
31
+ <Placeholder
32
+ rendering={props.rendering}
33
+ name="<%- helper.getAppPrefix(appPrefix, appName) %>jss-reuse-example"
34
+ renderEach={(component, index) => (
35
+ <div className="col-sm" key={index}>
36
+ {component}
37
+ </div>
38
+ )}
39
+ renderEmpty={(components) => <div className="col-sm">{components}</div>}
40
+ />
41
+ </div>
42
+ </StyleguideSpecimen>
43
+ );
44
+
45
+ export default StyleguideLayoutReuse;
@@ -0,0 +1,41 @@
1
+ import {
2
+ Text,
3
+ RichText,
4
+ Field,
5
+ useSitecoreContext,
6
+ withDatasourceCheck,
7
+ } from '@sitecore-jss/sitecore-jss-nextjs';
8
+ import { ComponentProps } from 'lib/component-props';
9
+
10
+ type StyleguideLayoutTabsTabProps = ComponentProps & {
11
+ fields: {
12
+ content: Field<string>;
13
+ title: Field<string>;
14
+ };
15
+ };
16
+
17
+ /**
18
+ * This is a single tab within the tabs sample component. These are added to the tabs placeholder.
19
+ * This component demonstrates conditionally altering rendering when in the Sitecore Experience Editor to improve
20
+ * author experience.
21
+ */
22
+ const StyleguideLayoutTabsTab = (props: StyleguideLayoutTabsTabProps): JSX.Element => {
23
+ const { sitecoreContext } = useSitecoreContext();
24
+
25
+ return (
26
+ <div data-e2e-class="styleguide-layout-tabs-tab">
27
+ {/*
28
+ When we're editing the tabs we stack each tab vertically,
29
+ which means there's no regular tab titles rendered.
30
+ So we conditionally render the tab title here, when editing. */}
31
+ {sitecoreContext && sitecoreContext.pageEditing && (
32
+ <Text tag="h5" field={props.fields.title} />
33
+ )}
34
+
35
+ {/* React.Fragment tells React to not use any wrapping tag for the component */}
36
+ <RichText field={props.fields.content} />
37
+ </div>
38
+ );
39
+ };
40
+
41
+ export default withDatasourceCheck()<StyleguideLayoutTabsTabProps>(StyleguideLayoutTabsTab);
@@ -0,0 +1,111 @@
1
+ import React, { ReactElement } from 'react';
2
+ import { withPlaceholder, withSitecoreContext, Text } from '@sitecore-jss/sitecore-jss-nextjs';
3
+ import StyleguideSpecimen from './Styleguide-Specimen';
4
+ import { ComponentWithContextProps } from 'lib/component-props';
5
+ import { StyleguideSpecimenFields } from 'lib/component-props/styleguide';
6
+
7
+ interface StyleguideLayoutTabsState {
8
+ activeTabIndex: number;
9
+ }
10
+
11
+ type StyleguideLayoutTabsProps = ComponentWithContextProps &
12
+ StyleguideSpecimenFields & {
13
+ name: string;
14
+ tabsPlaceholder: ReactElement[];
15
+ };
16
+
17
+ /**
18
+ * Demonstrates advanced component techniques in JSS.
19
+ * This example implements a simple-looking tabs component.
20
+ * Each tab is itself a child component added to a placeholder defined on the tabs component.
21
+ * The tab component introspects its child components to render the tab headings (i.e. the tab children render partial content in two places).
22
+ * When this component is edited in Sitecore Experience Editor, the tabbing behavior is turned off and each tab stacks on top of each other
23
+ * for easy inline editing.
24
+ */
25
+ class StyleguideLayoutTabs extends React.Component<
26
+ StyleguideLayoutTabsProps,
27
+ StyleguideLayoutTabsState
28
+ > {
29
+ constructor(props: StyleguideLayoutTabsProps) {
30
+ super(props);
31
+
32
+ this.state = {
33
+ activeTabIndex: 0,
34
+ };
35
+
36
+ this.setActiveTab = this.setActiveTab.bind(this);
37
+ }
38
+
39
+ setActiveTab(index: number) {
40
+ this.setState({ activeTabIndex: index });
41
+ }
42
+
43
+ render() {
44
+ const { tabsPlaceholder, sitecoreContext } = this.props;
45
+
46
+ let validTabIndex = 0;
47
+ const isEditing = sitecoreContext && sitecoreContext.pageEditing;
48
+
49
+ return (
50
+ <StyleguideSpecimen {...this.props} e2eId="styleguide-layout-tabs">
51
+ <ul className="nav nav-tabs">
52
+ {/*
53
+ When the page is editing, we hide the tab headings, because they are not updated when xEditor adds or removes a tab rendering.
54
+ Instead, we show the tab header inline with the tab contents (see Styleguide-Layout-Tabs-Tab).
55
+ */}
56
+ {!isEditing &&
57
+ (tabsPlaceholder || [])
58
+ .filter((tab: ReactElement) => tab.props && tab.props.fields)
59
+ .map((tab: ReactElement, index: number) => (
60
+ <li className="nav-item" key={`tab${index}`}>
61
+ <a
62
+ className={`nav-link ${index === this.state.activeTabIndex ? 'active' : null}`}
63
+ onClick={() => this.setActiveTab(index)}
64
+ href="#t"
65
+ >
66
+ <Text field={tab.props.fields.title} />
67
+ </a>
68
+ </li>
69
+ ))}
70
+ </ul>
71
+ <div className="p-3 border-left border-right border-bottom">
72
+ {(tabsPlaceholder || []).map((tab: ReactElement) => {
73
+ const isValid = tab.props && tab.props.fields;
74
+
75
+ // allow experience editor markup components to render
76
+ if (!isValid && isEditing) return tab;
77
+
78
+ validTabIndex += 1;
79
+
80
+ // we render the tab either if it's active - or we're editing,
81
+ // in which case we stack all tabs for visual editing
82
+ if (this.state.activeTabIndex === validTabIndex - 1 || isEditing) {
83
+ return tab;
84
+ }
85
+
86
+ return null;
87
+ })}
88
+ </div>
89
+ </StyleguideSpecimen>
90
+ );
91
+ }
92
+ }
93
+
94
+ // This is a _higher order component_ that will wrap our component and inject placeholder
95
+ // data into it as a prop (in this case, props.tabsPlaceholder).
96
+ // this another option compared to using the <Placeholder> component;
97
+ // in this case, chosen because we primarily need access to the _data_
98
+ // of the placeholder.
99
+ const tabsComponentWithPlaceholderInjected = withPlaceholder({
100
+ placeholder: '<%- helper.getAppPrefix(appPrefix, appName) %>jss-tabs',
101
+ prop: 'tabsPlaceholder',
102
+ })(StyleguideLayoutTabs);
103
+
104
+ // We need to know if experience editor is active, to disable the dynamic tab behavior for editing.
105
+ // Using the same technique as injecting the placeholder, we wrap the component again to inject the
106
+ // `sitecoreContext` prop.
107
+ const tabsWithPlaceholderAndSitecoreContext = withSitecoreContext()<StyleguideLayoutTabsProps>(
108
+ tabsComponentWithPlaceholderInjected
109
+ );
110
+
111
+ export default tabsWithPlaceholderAndSitecoreContext;
@@ -0,0 +1,68 @@
1
+ import {
2
+ Placeholder,
3
+ getChildPlaceholder,
4
+ getFieldValue,
5
+ ComponentRendering,
6
+ HtmlElementRendering,
7
+ } from '@sitecore-jss/sitecore-jss-nextjs';
8
+ import { ComponentProps } from 'lib/component-props';
9
+
10
+ /**
11
+ * The main layout (columns) of the styleguide.
12
+ * Navigation is automatically generated based on the components added to the layout,
13
+ * and does not need to be manually maintained.
14
+ */
15
+ const StyleguideLayout = (props: ComponentProps): JSX.Element => {
16
+ const getRendering = (section: ComponentRendering | HtmlElementRendering) =>
17
+ section as ComponentRendering;
18
+
19
+ const convertUID = (uid?: string) => {
20
+ if (!uid) return '';
21
+ return uid.replace(/[{}]/g, '');
22
+ };
23
+
24
+ // this code reads the components in the child placeholders of this component,
25
+ // and projects them into the left navigation column for the styleguide
26
+ const sections = getChildPlaceholder(props.rendering, '<%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-layout')
27
+ .filter((section) => getFieldValue(getRendering(section), 'heading'))
28
+ .map((section) => ({
29
+ heading: getFieldValue<string>(getRendering(section), 'heading'),
30
+ id: `i${convertUID(getRendering(section).uid)}`,
31
+ children: getChildPlaceholder(getRendering(section), '<%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section')
32
+ .filter((component) => getFieldValue(getRendering(component), 'heading'))
33
+ .map((component) => ({
34
+ heading: getFieldValue<string>(getRendering(component), 'heading'),
35
+ id: `i${convertUID(getRendering(component).uid)}`,
36
+ })),
37
+ }))
38
+ .map((section) => (
39
+ <nav key={section.heading} className="nav flex-column pt-2">
40
+ <a href={`#${section.id}`} className="nav-item font-weight-bold">
41
+ {section.heading}
42
+ </a>
43
+ {section.children && (
44
+ <nav className="nav flex-column">
45
+ {section.children.map(
46
+ (child) =>
47
+ child.heading && (
48
+ <a key={child.id} href={`#${child.id}`}>
49
+ {child.heading}
50
+ </a>
51
+ )
52
+ )}
53
+ </nav>
54
+ )}
55
+ </nav>
56
+ ));
57
+
58
+ return (
59
+ <div className="row">
60
+ <div className="col-sm-8 col-lg-10">
61
+ <Placeholder name="<%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-layout" rendering={props.rendering} />
62
+ </div>
63
+ <div className="col-sm-4 col-lg-2 order-sm-first pt-2">{sections}</div>
64
+ </div>
65
+ );
66
+ };
67
+
68
+ export default StyleguideLayout;