From 86b869fb3e7db3ad0ccbf59600c29c43392ae9fc Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 24 Aug 2023 17:54:58 -0500 Subject: [PATCH 1/7] Added Next.js JSS application --- examples/cms-sitecore-xmcloud/.env.example | 58 + examples/cms-sitecore-xmcloud/.gitignore | 33 + .../cms-sitecore-xmcloud/.graphql-let.yml | 8 + examples/cms-sitecore-xmcloud/LICENSE.txt | 202 + examples/cms-sitecore-xmcloud/next-env.d.ts | 5 + examples/cms-sitecore-xmcloud/next.config.js | 69 + examples/cms-sitecore-xmcloud/package.json | 97 + .../cms-sitecore-xmcloud/public/favicon.ico | Bin 0 -> 15086 bytes .../cms-sitecore-xmcloud/public/sc_logo.svg | 20 + .../cms-sitecore-xmcloud/scripts/bootstrap.ts | 21 + .../scripts/config/index.ts | 39 + .../scripts/config/plugins/computed.ts | 21 + .../scripts/config/plugins/fallback.ts | 19 + .../scripts/config/plugins/package-json.ts | 22 + .../scripts/config/plugins/scjssconfig.ts | 29 + .../fetch-graphql-introspection-data.ts | 48 + .../scripts/generate-component-factory.ts | 97 + .../scripts/generate-config.ts | 63 + .../scripts/generate-plugins.ts | 138 + .../scripts/scaffold-component.ts | 95 + .../scripts/temp/.npmignore | 2 + .../scripts/temp/config-plugins.ts | 4 + .../scripts/templates/component-factory.ts | 142 + .../scripts/templates/component-src.ts | 27 + .../cms-sitecore-xmcloud/scripts/utils.ts | 64 + .../config/xmcloud-nextjs-starter.config | 165 + examples/cms-sitecore-xmcloud/src/Layout.tsx | 63 + .../cms-sitecore-xmcloud/src/Navigation.tsx | 27 + .../cms-sitecore-xmcloud/src/NotFound.tsx | 19 + examples/cms-sitecore-xmcloud/src/Scripts.tsx | 5 + .../cms-sitecore-xmcloud/src/assets/app.css | 39 + .../src/assets/basic/_component.scss | 18 + .../src/assets/basic/_container.scss | 79 + .../src/assets/basic/_fonts.scss | 1 + .../src/assets/basic/_footer.scss | 32 + .../src/assets/basic/_header.scss | 49 + .../src/assets/basic/_navigation.scss | 152 + .../src/assets/basic/_promo.scss | 58 + .../src/assets/basic/_rich-text.scss | 11 + .../src/assets/basic/_variables.scss | 10 + .../src/assets/basic/main.scss | 8 + .../cms-sitecore-xmcloud/src/assets/main.scss | 5 + .../src/assets/sass/_app.scss | 105 + .../src/assets/sass/abstracts/_functions.scss | 7 + .../src/assets/sass/abstracts/_mixins.scss | 121 + .../src/assets/sass/abstracts/_vars.scss | 3 + .../assets/sass/abstracts/vars/_colors.scss | 283 + .../sass/abstracts/vars/_fontSizes.scss | 16 + .../assets/sass/abstracts/vars/_margins.scss | 11 + .../src/assets/sass/base/fonts/_fonts.scss | 1 + .../src/assets/sass/base/fonts/index.scss | 1 + .../src/assets/sass/base/index.scss | 3 + .../assets/sass/base/links/_link-button.scss | 29 + .../src/assets/sass/base/links/index.scss | 1 + .../src/assets/sass/base/reset/_inputs.scss | 67 + .../src/assets/sass/base/reset/_links.scss | 14 + .../sass/base/reset/_ui-datepicker.scss | 7 + .../base/richtext/_richtext-files-icons.scss | 203 + .../assets/sass/base/richtext/_richtext.scss | 101 + .../src/assets/sass/base/richtext/index.scss | 2 + .../assets/sass/base/typehead/_typehead.scss | 95 + .../src/assets/sass/base/typehead/index.scss | 1 + .../_component-column-splitter.scss | 14 + .../sass/components/_component-container.scss | 21 + .../sass/components/_component-image.scss | 18 + .../components/_component-navigation.scss | 54 + .../sass/components/_component-promo.scss | 42 + .../_component-richtext-content.scss | 20 + .../sass/components/common/_alignment.scss | 26 + .../assets/sass/components/common/_boxed.scss | 16 + .../sass/components/common/_clearfix.scss | 11 + .../sass/components/common/_highlighted.scss | 63 + .../sass/components/common/_link-button.scss | 18 + .../sass/components/common/_promoted-box.scss | 3 + .../assets/sass/components/common/index.scss | 6 + .../sass/components/container/_bordered.scss | 24 + .../components/container/_title-row-box.scss | 69 + .../sass/components/container/index.scss | 1 + .../image-alignment/_image-left.scss | 3 + .../image-alignment/_image-right.scss | 3 + .../sass/components/image/_image-banner.scss | 15 + .../components/image/_image-default-size.scss | 6 + .../assets/sass/components/image/index.scss | 2 + .../src/assets/sass/components/index.scss | 17 + .../sass/components/layout/_acaindent.scss | 5 + .../sass/components/layout/_background.scss | 27 + .../assets/sass/components/layout/index.scss | 1 + .../link-list/_component-link-list.scss | 50 + .../components/link-list/_list-vertical.scss | 19 + .../sass/components/link-list/index.scss | 2 + .../navigation/_navigation-fat.scss | 57 + .../_navigation-main-horizontal-vertical.scss | 158 + .../navigation/_navigation-mobile.scss | 89 + .../navigation/_navigation-sidebar.scss | 29 + .../navigation/_sitemap-navigation.scss | 20 + .../sass/components/navigation/index.scss | 5 + .../promo/_absolute-bottom-link.scss | 8 + .../sass/components/promo/_promo-hero.scss | 42 + .../sass/components/promo/_promo-shadow.scss | 43 + .../assets/sass/components/promo/index.scss | 3 + .../rich-text/_rich-text-lists.scss | 63 + .../sass/components/rich-text/index.scss | 1 + .../spacing/_background-colors.scss | 14 + .../sass/components/spacing/_indent.scss | 10 + .../assets/sass/components/spacing/index.scss | 2 + .../components/title/_component-title.scss | 25 + .../assets/sass/components/title/index.scss | 1 + .../src/assets/sass/main.scss | 4 + .../src/assets/sass/variants/index.scss | 6 + .../assets/sass/variants/link-list/index.scss | 0 .../sass/variants/navigation/index.scss | 0 .../sass/variants/page-content/index.scss | 0 .../src/assets/sass/variants/promo/index.scss | 0 .../assets/sass/variants/rich-text/index.scss | 0 .../src/assets/sass/variants/title/index.scss | 0 .../src/components/ColumnSplitter.tsx | 65 + .../src/components/Container.tsx | 67 + .../src/components/ContentBlock.tsx | 29 + .../src/components/FEaaSWrapper.tsx | 18 + .../src/components/Image.tsx | 97 + .../src/components/LinkList.tsx | 92 + .../src/components/Navigation.tsx | 170 + .../src/components/PageContent.tsx | 68 + .../PartialDesignDynamicPlaceholder.tsx | 20 + .../src/components/Promo.tsx | 90 + .../src/components/RichText.tsx | 32 + .../src/components/RowSplitter.tsx | 55 + .../src/components/Title.tsx | 101 + .../src/lib/component-props/index.ts | 23 + .../src/lib/data-fetcher.ts | 18 + .../src/lib/dictionary-service-factory.ts | 39 + .../src/lib/extract-path/index.ts | 38 + .../src/lib/layout-service-factory.ts | 34 + .../src/lib/middleware/index.ts | 32 + .../src/lib/middleware/plugins/redirects.ts | 40 + .../src/lib/next-config/plugins/graphql.js | 35 + .../src/lib/next-config/plugins/robots.js | 19 + .../src/lib/next-config/plugins/sass.js | 22 + .../src/lib/next-config/plugins/sitemap.js | 19 + .../src/lib/page-props-factory/index.ts | 50 + .../plugins/component-props.ts | 43 + .../page-props-factory/plugins/normal-mode.ts | 89 + .../plugins/preview-mode.ts | 34 + .../lib/page-props-factory/plugins/site.ts | 23 + .../src/lib/page-props.ts | 18 + .../src/lib/site-resolver/index.ts | 28 + .../src/lib/site-resolver/plugins/default.ts | 18 + .../src/lib/sitemap-fetcher/index.ts | 27 + .../plugins/graphql-sitemap-service.ts | 31 + .../cms-sitecore-xmcloud/src/middleware.ts | 19 + .../cms-sitecore-xmcloud/src/pages/404.tsx | 55 + .../cms-sitecore-xmcloud/src/pages/500.tsx | 74 + .../src/pages/[[...path]].tsx | 114 + .../cms-sitecore-xmcloud/src/pages/_app.tsx | 23 + .../cms-sitecore-xmcloud/src/pages/_error.tsx | 35 + .../src/pages/api/editing/data/[key].ts | 25 + .../src/pages/api/editing/render.ts | 31 + .../src/pages/api/healthz.ts | 12 + .../src/pages/api/robots.ts | 29 + .../src/pages/api/sitemap.ts | 79 + .../cms-sitecore-xmcloud/src/temp/.gitignore | 3 + .../src/temp/GraphQLIntrospectionResult.json | 22205 ++++++++++++++++ examples/cms-sitecore-xmcloud/tsconfig.json | 38 + .../tsconfig.scripts.json | 9 + 164 files changed, 28606 insertions(+) create mode 100644 examples/cms-sitecore-xmcloud/.env.example create mode 100644 examples/cms-sitecore-xmcloud/.gitignore create mode 100644 examples/cms-sitecore-xmcloud/.graphql-let.yml create mode 100644 examples/cms-sitecore-xmcloud/LICENSE.txt create mode 100644 examples/cms-sitecore-xmcloud/next-env.d.ts create mode 100644 examples/cms-sitecore-xmcloud/next.config.js create mode 100644 examples/cms-sitecore-xmcloud/package.json create mode 100644 examples/cms-sitecore-xmcloud/public/favicon.ico create mode 100644 examples/cms-sitecore-xmcloud/public/sc_logo.svg create mode 100644 examples/cms-sitecore-xmcloud/scripts/bootstrap.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/config/index.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/config/plugins/computed.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/config/plugins/fallback.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/config/plugins/package-json.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/config/plugins/scjssconfig.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/fetch-graphql-introspection-data.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/generate-component-factory.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/generate-config.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/generate-plugins.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/scaffold-component.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/temp/.npmignore create mode 100644 examples/cms-sitecore-xmcloud/scripts/temp/config-plugins.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/templates/component-factory.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/templates/component-src.ts create mode 100644 examples/cms-sitecore-xmcloud/scripts/utils.ts create mode 100644 examples/cms-sitecore-xmcloud/sitecore/config/xmcloud-nextjs-starter.config create mode 100644 examples/cms-sitecore-xmcloud/src/Layout.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/Navigation.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/NotFound.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/Scripts.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/assets/app.css create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_component.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_container.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_fonts.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_footer.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_header.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_navigation.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_promo.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_rich-text.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/_variables.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/basic/main.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/main.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/_app.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_functions.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_mixins.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_vars.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_colors.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_fontSizes.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_margins.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/_fonts.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/links/_link-button.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/links/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_inputs.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_links.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_ui-datepicker.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext-files-icons.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-column-splitter.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-container.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-image.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-navigation.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-promo.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-richtext-content.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_alignment.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_boxed.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_clearfix.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_highlighted.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_link-button.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_promoted-box.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/common/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_bordered.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_title-row-box.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/container/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-left.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-right.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-banner.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-default-size.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/image/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_acaindent.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_background.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_component-link-list.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_list-vertical.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-fat.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-main-horizontal-vertical.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-mobile.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-sidebar.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_sitemap-navigation.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_absolute-bottom-link.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-hero.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-shadow.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/_rich-text-lists.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_background-colors.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_indent.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/title/_component-title.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/components/title/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/main.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/link-list/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/navigation/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/page-content/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/promo/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/rich-text/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/assets/sass/variants/title/index.scss create mode 100644 examples/cms-sitecore-xmcloud/src/components/ColumnSplitter.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/Container.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/ContentBlock.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/FEaaSWrapper.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/Image.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/LinkList.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/Navigation.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/PageContent.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/PartialDesignDynamicPlaceholder.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/Promo.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/RichText.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/RowSplitter.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/components/Title.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/lib/component-props/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/data-fetcher.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/dictionary-service-factory.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/extract-path/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/layout-service-factory.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/middleware/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/middleware/plugins/redirects.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/next-config/plugins/graphql.js create mode 100644 examples/cms-sitecore-xmcloud/src/lib/next-config/plugins/robots.js create mode 100644 examples/cms-sitecore-xmcloud/src/lib/next-config/plugins/sass.js create mode 100644 examples/cms-sitecore-xmcloud/src/lib/next-config/plugins/sitemap.js create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/component-props.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/normal-mode.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/preview-mode.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/site.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/page-props.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/site-resolver/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/site-resolver/plugins/default.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/sitemap-fetcher/index.ts create mode 100644 examples/cms-sitecore-xmcloud/src/lib/sitemap-fetcher/plugins/graphql-sitemap-service.ts create mode 100644 examples/cms-sitecore-xmcloud/src/middleware.ts create mode 100644 examples/cms-sitecore-xmcloud/src/pages/404.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/pages/500.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/pages/[[...path]].tsx create mode 100644 examples/cms-sitecore-xmcloud/src/pages/_app.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/pages/_error.tsx create mode 100644 examples/cms-sitecore-xmcloud/src/pages/api/editing/data/[key].ts create mode 100644 examples/cms-sitecore-xmcloud/src/pages/api/editing/render.ts create mode 100644 examples/cms-sitecore-xmcloud/src/pages/api/healthz.ts create mode 100644 examples/cms-sitecore-xmcloud/src/pages/api/robots.ts create mode 100644 examples/cms-sitecore-xmcloud/src/pages/api/sitemap.ts create mode 100644 examples/cms-sitecore-xmcloud/src/temp/.gitignore create mode 100644 examples/cms-sitecore-xmcloud/src/temp/GraphQLIntrospectionResult.json create mode 100644 examples/cms-sitecore-xmcloud/tsconfig.json create mode 100644 examples/cms-sitecore-xmcloud/tsconfig.scripts.json diff --git a/examples/cms-sitecore-xmcloud/.env.example b/examples/cms-sitecore-xmcloud/.env.example new file mode 100644 index 0000000000000..e1f160332f29d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/.env.example @@ -0,0 +1,58 @@ +# For development purposes, note Next.js supports a .env.local +# file, which is already configured to be git ignored. +# Read more about Next.js support of environment variables here: +# https://nextjs.org/docs/basic-features/environment-variables +JSS_APP_NAME= + +# The public URL to use for absolute URLs, which are required when +# the Next.js app is run within Sitecore editors. +# This should match the `serverSideRenderingEngineApplicationUrl` +# in your Sitecore configuration (see \sitecore\config\xmcloud-nextjs-starter.config). +# Be sure to update these values accordingly as your public endpoint changes. +# See https://jss.sitecore.com/docs/fundamentals/services/view-engine +PUBLIC_URL=http://localhost:3000 + +# To secure the Sitecore editor endpoint exposed by your Next.js app +# (`/api/editing/render` by default), a secret token is used. This (client-side) +# value must match your server-side value (see \sitecore\config\xmcloud-nextjs-starter.config). +# We recommend an alphanumeric value of at least 16 characters. +JSS_EDITING_SECRET= + +# Your Sitecore API key is needed to build the app. Typically, the API key is +# defined in `scjssconfig.json` (as `sitecore.apiKey`). This file may not exist +# when building locally (if you've never run `jss setup`), or when building in a +# higher environment (since `scjssconfig.json` is ignored from source control). +# In this case, use this environment variable to provide the value at build time. +SITECORE_API_KEY= + +# Your Sitecore API hostname is needed to build the app. Typically, the API host is +# defined in `scjssconfig.json` (as `sitecore.layoutServiceHost`). This file may +# not exist when building locally (if you've never run `jss setup`), or when building +# in a higher environment (since `scjssconfig.json` is ignored from source control). +# In this case, use this environment variable to provide the value at build time. +SITECORE_API_HOST= + +# Your GraphQL Edge endpoint. This is required for Sitecore Experience Edge. +# For Sitecore XM, this is typically optional. By default, the endpoint is calculated using +# the resolved Sitecore API hostname + the `graphQLEndpointPath` defined in your `package.json`. +GRAPH_QL_ENDPOINT= + +# Your default app language. +DEFAULT_LANGUAGE= + +# The way in which layout and dictionary data is fetched from Sitecore +FETCH_WITH=GraphQL + +# Indicates whether SSG `getStaticPaths` pre-render any pages +# Set the environment variable DISABLE_SSG_FETCH=true +# to enable full ISR (Incremental Static Regeneration) flow +DISABLE_SSG_FETCH= + +# Sitecore JSS npm packages utilize the debug module for debug logging. +# https://www.npmjs.com/package/debug +# Set the DEBUG environment variable to 'sitecore-jss:*' to see all logs: +#DEBUG=sitecore-jss:* +# Or be selective and show for example only layout service logs: +#DEBUG=sitecore-jss:layout +# Or everything BUT layout service logs: +#DEBUG=sitecore-jss:*,-sitecore-jss:layout diff --git a/examples/cms-sitecore-xmcloud/.gitignore b/examples/cms-sitecore-xmcloud/.gitignore new file mode 100644 index 0000000000000..b9d296990d879 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/.gitignore @@ -0,0 +1,33 @@ +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +/node_modules + +# testing +/coverage + +# next.js +/.next*/ +/out/ + +# graphql code generation +/.generated +*.graphql.d.ts +*.graphqls.d.ts + +# misc +.DS_Store + +# local env files +.env.local +.env.*.local + +# Log files +*.log* + +# sitecore +scjssconfig.json +*.deploysecret.config + +# vercel +.vercel \ No newline at end of file diff --git a/examples/cms-sitecore-xmcloud/.graphql-let.yml b/examples/cms-sitecore-xmcloud/.graphql-let.yml new file mode 100644 index 0000000000000..85b6e0d8a2f26 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/.graphql-let.yml @@ -0,0 +1,8 @@ +schema: + - './src/temp/GraphQLIntrospectionResult.json' +documents: 'src/**/*.graphql' +plugins: + - typescript-operations + - typed-document-node +config: + useIndexSignature: true diff --git a/examples/cms-sitecore-xmcloud/LICENSE.txt b/examples/cms-sitecore-xmcloud/LICENSE.txt new file mode 100644 index 0000000000000..d645695673349 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/examples/cms-sitecore-xmcloud/next-env.d.ts b/examples/cms-sitecore-xmcloud/next-env.d.ts new file mode 100644 index 0000000000000..4f11a03dc6cc3 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/cms-sitecore-xmcloud/next.config.js b/examples/cms-sitecore-xmcloud/next.config.js new file mode 100644 index 0000000000000..ca92b3473e276 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/next.config.js @@ -0,0 +1,69 @@ +const jssConfig = require('./src/temp/config') +const { getPublicUrl } = require('@sitecore-jss/sitecore-jss-nextjs') +const plugins = require('./src/temp/next-config-plugins') || {} + +const publicUrl = getPublicUrl() + +/** + * @type {import('next').NextConfig} + */ +const nextConfig = { + // Set assetPrefix to our public URL + assetPrefix: publicUrl, + + // Allow specifying a distinct distDir when concurrently running app in a container + distDir: process.env.NEXTJS_DIST_DIR || '.next', + + // Make the same PUBLIC_URL available as an environment variable on the client bundle + env: { + PUBLIC_URL: publicUrl, + }, + + i18n: { + // These are all the locales you want to support in your application. + // These should generally match (or at least be a subset of) those in Sitecore. + locales: ['en'], + // This is the locale that will be used when visiting a non-locale + // prefixed path e.g. `/styleguide`. + defaultLocale: jssConfig.defaultLanguage, + }, + + // Enable React Strict Mode + reactStrictMode: true, + + async rewrites() { + // When in connected mode we want to proxy Sitecore paths off to Sitecore + return [ + // API endpoints + { + source: '/sitecore/api/:path*', + destination: `${jssConfig.sitecoreApiHost}/sitecore/api/:path*`, + }, + // media items + { + source: '/-/:path*', + destination: `${jssConfig.sitecoreApiHost}/-/:path*`, + }, + // visitor identification + { + source: '/layouts/system/:path*', + destination: `${jssConfig.sitecoreApiHost}/layouts/system/:path*`, + }, + // healthz check + { + source: '/healthz', + destination: '/api/healthz', + }, + // rewrite for Sitecore service pages + { + source: '/sitecore/service/:path*', + destination: `${jssConfig.sitecoreApiHost}/sitecore/service/:path*`, + }, + ] + }, +} + +module.exports = () => { + // Run the base config through any configured plugins + return Object.values(plugins).reduce((acc, plugin) => plugin(acc), nextConfig) +} diff --git a/examples/cms-sitecore-xmcloud/package.json b/examples/cms-sitecore-xmcloud/package.json new file mode 100644 index 0000000000000..a6e2e4a25503a --- /dev/null +++ b/examples/cms-sitecore-xmcloud/package.json @@ -0,0 +1,97 @@ +{ + "name": "xmcloud-nextjs-starter", + "description": "Application utilizing Sitecore JavaScript Services and Next.js", + "version": "21.1.6", + "private": true, + "config": { + "appName": "xmcloud-nextjs-starter", + "rootPlaceholders": [ + "jss-main" + ], + "sitecoreConfigPath": "/App_Config/Include/zzz", + "graphQLEndpointPath": "/sitecore/api/graph/edge", + "language": "en", + "templates": [ + "nextjs", + "nextjs-sxa" + ] + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "author": { + "name": "Sitecore Corporation", + "url": "https://jss.sitecore.com" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/sitecore/jss.git" + }, + "bugs": { + "url": "https://github.com/sitecore/jss/issues" + }, + "license": "Apache-2.0", + "dependencies": { + "@sitecore-jss/sitecore-jss-nextjs": "~21.1.6", + "bootstrap": "^5.1.3", + "font-awesome": "^4.7.0", + "graphql": "~15.8.0", + "graphql-tag": "^2.12.6", + "next": "^13.1.6", + "next-localization": "^0.12.0", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@graphql-codegen/cli": "^1.21.8", + "@graphql-codegen/import-types-preset": "^2.2.6", + "@graphql-codegen/plugin-helpers": "^3.1.2", + "@graphql-codegen/typed-document-node": "^2.3.12", + "@graphql-codegen/typescript": "^2.8.7", + "@graphql-codegen/typescript-operations": "^2.5.12", + "@graphql-codegen/typescript-resolvers": "^2.7.12", + "@graphql-typed-document-node/core": "^3.1.1", + "@sitecore-jss/sitecore-jss-cli": "~21.1.6", + "@types/node": "^18.11.18", + "@types/react": "^18.0.12", + "@types/react-dom": "^18.0.5", + "@typescript-eslint/eslint-plugin": "^5.49.0", + "@typescript-eslint/parser": "^5.49.0", + "chalk": "~4.1.2", + "chokidar": "~3.5.3", + "constant-case": "^3.0.4", + "cross-env": "~7.0.3", + "dotenv": "^16.0.3", + "eslint": "^8.32.0", + "eslint-config-next": "^13.1.5", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-yaml": "^0.5.0", + "graphql-let": "^0.18.6", + "npm-run-all": "~4.1.5", + "prettier": "^2.8.3", + "sass": "^1.52.3", + "sass-alias": "^1.0.5", + "ts-node": "^10.9.1", + "tsconfig-paths": "^4.1.2", + "typescript": "~4.9.4", + "yaml-loader": "^0.8.0" + }, + "scripts": { + "dev": "npm run next:dev", + "start": "npm run next:start", + "jss": "jss", + "lint": "eslint ./src/**/*.tsx ./src/**/*.ts ./scripts/**/*.ts", + "bootstrap": "ts-node --project tsconfig.scripts.json scripts/bootstrap.ts", + "build": "npm-run-all --serial bootstrap next:build", + "graphql:update": "ts-node --project tsconfig.scripts.json ./scripts/fetch-graphql-introspection-data.ts", + "next:build": "next build", + "next:dev": "cross-env NODE_OPTIONS='--inspect' next dev", + "next:start": "next start", + "scaffold": "ts-node --project tsconfig.scripts.json scripts/scaffold-component.ts", + "start:connected": "npm-run-all --serial bootstrap --parallel next:dev start:watch-components", + "start:production": "npm-run-all --serial bootstrap next:build next:start", + "start:watch-components": "ts-node --project tsconfig.scripts.json scripts/generate-component-factory.ts --watch" + } +} diff --git a/examples/cms-sitecore-xmcloud/public/favicon.ico b/examples/cms-sitecore-xmcloud/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..065a432e4186a62ed48411fa6ad2c72fafd73f58 GIT binary patch literal 15086 zcmchd36K@V8GvV55DXG1QyLXj5shGWovc_0}-XynTC^SM||7ef9cg!ZY@Z;1 zB5YI2me$lEs}mdoFG6eANZP(~pI=3ndy3uM_8KxIIFzHuIPw%sfQ#W8 za4*gR%Vj3q375j@a2nhQZ$nFKausbxLAP?pK-=GgF|m}7zM|fEuYYfW1yIg-Z8H~) zy~n~8unbD+vd^EPQ%hr@%|KWRrR2R&{naoT{+npqNZxU4&mwpe^s({Ly0lE|E{3Dv zA#e?*+l1%k)E!#Ne(E=d*(GEsYd%~E`d)p`uXd_`8cczk;0|yfST+ePn*r}Za?L11 zokPHV(g4BcbowlH)mdYpyaGl*Qg*t(G4wC+I%xOPFctm@&wy)aVG-x>Gx!?xy?c8O zI1b0<946(z!}IUJ`6xApzf=FMI|pSu!rPFPnau0sGeFyIHyPZ6x57y9KGPo#gR|g# zaGpkiV{~l#+VL2pyaPFY%YvQ{$^Q|?fMX8j$<(#EXL1gB?gZ|mWV>Yk6Y8`{|LN!2 z;o;cS=y?}B>ohkGHpmh{Hc;OK^lNf_A#dN& za5?ze(XJmd)a9ON0N2q~umoJ|?xQE+Q*bP0!wq+ETY`~^z(KZ zp6HCMZg2s(kKNOk!AGFo<3PW=$D9l2XcQ#v4*BJj?*k{os+=~rQ9cO1pD>}_S>&w; zQ$Sm0g1**XZE`HZ#>M211NU?&3#oH<4qTT}XB+Ds8*io^|3mH;;M&mcOF*9o+d`@h zr$Hg3&NkEG@tivS(C#%~YUIe*KkhMYH`cnQg6$!_mNL(Z@SIHNQeKx+_ZsCJm(t(f zI_1NQ;QBos=0nmx^N+yUkQIkK%d*y%{pLW2uKTRRRBYR(XCr7vTdNv)E z)5i67ChU|`Z-38|&Dv{cUVmf{fyI#JTg&v{8IW~$y-)dG&>ilBEE$e*XrBJ|mLt0Y zwg=a^F*9j{?z(|E?X|U3f8=)qW8^cSuca1#4S8#O zSddAZzVIf5u_aT-)!a7p`7ToQYzh~{bl44i&rjMC^6r`Kf(_)INAIwqKAn0#?i<>F zmnnKW!w=v}NZS#f-4|G{I z17$o6n`iayh%#hr`>~LG2TR)SzVQ7yGp19%0Xz!HKI!}{>O1^gMy7lCB*?Q}JLbTq zrF=!bF|`iTb|;_bQGX-R(mH8p3^)@?`6I~o9J~<*LvP3(3w6f19^jd; ze9xA=_#WhYZ$1}V{N9%whwb4k(9c0usZ>3$!EJCp{00t(L&3G?J!~922FsvSoCtdK z-+55>|GlKf(1pIvuQ4mgEH~9Yee1iSciB?wBTJ_9dNQ{zXHIX+K?Y;^2 zhUV}3ZMCzde&}#t>$KcbZ=|`2ZHCi?-7f@ z@feSMe-QVuWuA)SZS4YtZ(}pOjGOdfEuBL@3sx+xw99DY1cTeXIu?9rj1|BSqt4@Pw@Pj4a?yx2>aG^;6s=Lqrm;z z?r(g^@T@%mZh>V`PF%5#apQJyE#u|Z|LC_lOaS+D7-wr!?+BBDzoaYwNBbHuhLqB0 zTyhSir5N=RZT2t60@~@b#gL_YCFR~_9s%z&)8J;f5%jn7pLb7xo4UhF*+9MPW+9|? z8>c*b?*(;)Smr%Qn~Y%#z&JM+w9WOHma~Mifmt?C?mM=!(|x?J+zrl$^Qqi7;RSda zwCgSS0_>|z`p3ANHHVgMp0t5y&(BLCty`bzWA(ibvq0H1;Xg1JoR62G0G8=XnY|5Bk$H@mJ6v2Er*Y2ByNJpg#Tk5NNNm{C?`aNNb1m6JHiRz9u9Tike>htLPc_& zl*-e#8@T4)1^3A^cmSLa*T*IB4g@{=_;i?_D6?)U42D+!-6?&#!wukGydR96pMrAr zi~BR^H~km9k}7k(w)y|(=-UtU`yG&+SMNC2z-kCKSf7qp6H58HoH}H>m))D%5OjS; z-v2KMal&%TlFycnDo01DHptiy9IyL)6)4wK{mJn*@SN6vVJX?=)FHDPTmu(@>)>&i z0p~zkzxy@#$aH);I!d)cMjvo)=YZ>5Cc&wY9IyU&ZzT154{nY%rS#<0(SI*+?I-0L zAFl%UcPM{@yfH33n>ue>=E-iUoW9+_u_k4jHxAsHD!-fOp%B)H?X+)bOM3F^>DvQb z|DQmx;Y;!(!8r+K#>G=$YtRp&+_V7e=jmvvoW5P)Ab1Si@Atvqius^tG0)pW1&oDI zZrWs9OL|(WN6rRtBK#H>LQ==IJo84-bO!E5K7BqJ$IH62m9hgF8-n9c>h^5kJM<&p z2|VwTZOnU~^$+b@o6=X^-Vc*8SGi-LY3xBJ&zperp0+{19SvpgN!mK6JA>z6TDNzE z&4S)!O8M@PUW?je%$N!_koz~=)OCh!;9OV&>9H)LtfW7wKL9+x(tUk4rpy5M(hwK` z{b3Lo+l(dZO^?~W>OMF*-n=~R_5fpNmYiT$BlRobb4bRIP@hbnp-owLsbCZB`+(~t zd0r%CmXkLIjfd(Ww>2sKj3fKN6mUO&11;&b%~H4toS)q9*5%rQjCH{Ed^S7`+OiUy z1N9kS)%hs=6?TQPzB|Qre1NE}X!=aUHSW;m6?kz6Q_obHMerEgTNs^`3{mBL{nOAsE2Z8s%>erwH^P|h@7M=t z^$TUx_l5gG8B@XaVZSAtCt?{qv8yM+Ea1U6% z0`7uez%H;842DVYG1$g&Y?2%)&l|&4pl!BsPPNfKVgKkq*KO})-;k%=JL*qB{qKV@ z%>DZT+zp4pT4QUd;@c^sD6sNs@!S}wDy*TVj-XPcigd~<>OYO5C!Sc-$G-mqH(reZ literal 0 HcmV?d00001 diff --git a/examples/cms-sitecore-xmcloud/public/sc_logo.svg b/examples/cms-sitecore-xmcloud/public/sc_logo.svg new file mode 100644 index 0000000000000..1be7e78814a1d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/public/sc_logo.svg @@ -0,0 +1,20 @@ + + + + Logo + Created with Sketch. + + + + + + \ No newline at end of file diff --git a/examples/cms-sitecore-xmcloud/scripts/bootstrap.ts b/examples/cms-sitecore-xmcloud/scripts/bootstrap.ts new file mode 100644 index 0000000000000..7ef1ffeceac22 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/bootstrap.ts @@ -0,0 +1,21 @@ +/* + BOOTSTRAPPING + The bootstrap process runs before build, and generates JS that needs to be + included into the build - specifically, plugins, the global config module, + and the component name to component mapping. +*/ + +/* + PLUGINS GENERATION +*/ +import './generate-plugins' + +/* + CONFIG GENERATION +*/ +import './generate-config' + +/* + COMPONENT FACTORY GENERATION +*/ +import './generate-component-factory' diff --git a/examples/cms-sitecore-xmcloud/scripts/config/index.ts b/examples/cms-sitecore-xmcloud/scripts/config/index.ts new file mode 100644 index 0000000000000..932cf3e42dbcd --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/config/index.ts @@ -0,0 +1,39 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const plugins = require('scripts/temp/config-plugins') + +/** + * JSS configuration object + */ +export interface JssConfig extends Record { + sitecoreApiKey?: string + sitecoreApiHost?: string + jssAppName?: string + graphQLEndpointPath?: string + defaultLanguage?: string + graphQLEndpoint?: string +} + +export interface ConfigPlugin { + /** + * Detect order when the plugin should be called, e.g. 0 - will be called first (can be a plugin which data is required for other plugins) + */ + order: number + /** + * A function which will be called during config generation + * @param {JssConfig} config Current (accumulated) config + */ + exec(config: JssConfig): Promise +} + +export class JssConfigFactory { + public async create(defaultConfig: JssConfig = {}): Promise { + return (Object.values(plugins) as ConfigPlugin[]) + .sort((p1, p2) => p1.order - p2.order) + .reduce( + (promise, plugin) => promise.then((config) => plugin.exec(config)), + Promise.resolve(defaultConfig) + ) + } +} + +export const jssConfigFactory = new JssConfigFactory() diff --git a/examples/cms-sitecore-xmcloud/scripts/config/plugins/computed.ts b/examples/cms-sitecore-xmcloud/scripts/config/plugins/computed.ts new file mode 100644 index 0000000000000..2a898db95f07e --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/config/plugins/computed.ts @@ -0,0 +1,21 @@ +import { ConfigPlugin, JssConfig } from '..' + +/** + * This plugin will set computed config props. + * The "graphQLEndpoint" is an example of making a _computed_ config setting + * based on other config settings. + */ +class ComputedPlugin implements ConfigPlugin { + // should come after other plugins (but before fallback) + order = 10 + + async exec(config: JssConfig) { + return Object.assign({}, config, { + graphQLEndpoint: + config.graphQLEndpoint || + `${config.sitecoreApiHost}${config.graphQLEndpointPath}`, + }) + } +} + +export const computedPlugin = new ComputedPlugin() diff --git a/examples/cms-sitecore-xmcloud/scripts/config/plugins/fallback.ts b/examples/cms-sitecore-xmcloud/scripts/config/plugins/fallback.ts new file mode 100644 index 0000000000000..d428dca3cc524 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/config/plugins/fallback.ts @@ -0,0 +1,19 @@ +import { ConfigPlugin, JssConfig } from '..' + +/** + * This config will set fallback values for properties that were left empty + * If neither env, nor other places had a proper value, this will ensure a fallback is set + */ +class FallbackPlugin implements ConfigPlugin { + // should always come last + order = 100 + + async exec(config: JssConfig) { + return Object.assign({}, config, { + defaultLanguage: config.defaultLanguage || 'en', + sitecoreApiKey: config.sitecoreApiKey || 'no-api-key-set', + }) + } +} + +export const fallbackPlugin = new FallbackPlugin() diff --git a/examples/cms-sitecore-xmcloud/scripts/config/plugins/package-json.ts b/examples/cms-sitecore-xmcloud/scripts/config/plugins/package-json.ts new file mode 100644 index 0000000000000..7b767c98a198c --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/config/plugins/package-json.ts @@ -0,0 +1,22 @@ +import { ConfigPlugin, JssConfig } from '..' +import packageConfig from 'package.json' + +/** + * This plugin will set config props based on package.json. + */ +class PackageJsonPlugin implements ConfigPlugin { + order = 1 + + async exec(config: JssConfig) { + if (!packageConfig.config) return config + + return Object.assign({}, config, { + jssAppName: config.jssAppName || packageConfig.config.appName, + graphQLEndpointPath: + config.graphQLEndpointPath || packageConfig.config.graphQLEndpointPath, + defaultLanguage: config.defaultLanguage || packageConfig.config.language, + }) + } +} + +export const packageJsonPlugin = new PackageJsonPlugin() diff --git a/examples/cms-sitecore-xmcloud/scripts/config/plugins/scjssconfig.ts b/examples/cms-sitecore-xmcloud/scripts/config/plugins/scjssconfig.ts new file mode 100644 index 0000000000000..47c5e8d157edd --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/config/plugins/scjssconfig.ts @@ -0,0 +1,29 @@ +import { ConfigPlugin, JssConfig } from '..' + +/** + * This plugin will set config props based on scjssconfig.json. + * scjssconfig.json may not exist if you've never run `jss setup` (development) + * or are depending on environment variables instead (production). + */ +class ScJssConfigPlugin implements ConfigPlugin { + order = 1 + + async exec(config: JssConfig) { + let scJssConfig + try { + scJssConfig = require('scjssconfig.json') + } catch (e) { + return config + } + + if (!scJssConfig) return config + + return Object.assign({}, config, { + sitecoreApiKey: config.sitecoreApiKey || scJssConfig.sitecore?.apiKey, + sitecoreApiHost: + config.sitecoreApiHost || scJssConfig.sitecore?.layoutServiceHost, + }) + } +} + +export const scjssconfigPlugin = new ScJssConfigPlugin() diff --git a/examples/cms-sitecore-xmcloud/scripts/fetch-graphql-introspection-data.ts b/examples/cms-sitecore-xmcloud/scripts/fetch-graphql-introspection-data.ts new file mode 100644 index 0000000000000..2a66c72352712 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/fetch-graphql-introspection-data.ts @@ -0,0 +1,48 @@ +import { GraphQLRequestClient } from '@sitecore-jss/sitecore-jss-nextjs' +import fs from 'fs' +import { getIntrospectionQuery } from 'graphql' + +// This script load graphql introspection data in order to use graphql code generator and generate typescript types +// The `jss graphql:update` command should be executed when Sitecore templates related to the site are altered. + +let jssConfig + +try { + // eslint-disable-next-line + jssConfig = require('../src/temp/config') +} catch (e) { + console.error( + 'Unable to require JSS config. Ensure `jss setup` has been run, and the app has been started at least once after setup.' + ) + console.error(e) + process.exit(1) +} + +console.log( + `Fetch graphql introspection data from ${jssConfig.graphQLEndpoint}...` +) + +const client = new GraphQLRequestClient(jssConfig.graphQLEndpoint, { + apiKey: jssConfig.sitecoreApiKey, +}) + +client + .request(getIntrospectionQuery()) + .then((result) => { + fs.writeFile( + './src/temp/GraphQLIntrospectionResult.json', + JSON.stringify(result, null, 2), + (err) => { + if (err) { + console.error('Error writing GraphQLIntrospectionResult file', err) + return + } + + console.log('GraphQL Introspection Data successfully fetched!') + } + ) + }) + .catch((e) => { + console.error(e) + process.exit(1) + }) diff --git a/examples/cms-sitecore-xmcloud/scripts/generate-component-factory.ts b/examples/cms-sitecore-xmcloud/scripts/generate-component-factory.ts new file mode 100644 index 0000000000000..a5a3b8a3866ae --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/generate-component-factory.ts @@ -0,0 +1,97 @@ +import fs from 'fs' +import path from 'path' +import generateComponentFactory, { + ComponentFile, + PackageDefinition, +} from './templates/component-factory' +import { getItems, watchItems } from './utils' + +/* + COMPONENT FACTORY GENERATION + Generates the `/src/temp/componentFactory.ts` file, which maps JSS React components + to Sitecore renderings. + + The component factory is a mapping between a string name and a React component instance. + When the Sitecore Layout service returns a layout definition, it returns named components. + This mapping is used to construct the component hierarchy for the layout. + + Generating the componentFactory is optional, and it can be maintained manually if preferred. + + The default convention uses the component's filename (without the extension) as the component + name. For example, the file `/components/ComponentName.ts` would map to component `ComponentName`. + This can be customized in writeComponentFactory(). + + This script supports two modes. In default mode, the component factory file is written once. + In watch mode, the component factory source folder is watched, and componentFactory.ts is + regenerated whenever files are added or deleted. Run in watch mode by passing a `--watch` argument + when calling the script. +*/ + +const componentFactoryPath = path.resolve('src/temp/componentFactory.ts') +const componentRootPath = 'src/components' + +const isWatch = process.argv.some((arg) => arg === '--watch') + +;(isWatch ? watchComponentFactory : writeComponentFactory)() + +/** + * Watches component directory for changes. When files are added or deleted, the component factory + * file (componentFactory.ts) is regenerated. This is used during `jss start` to pick up new or + * removed components at runtime. + */ +function watchComponentFactory() { + console.log( + `Watching for changes to component factory sources in ${componentRootPath}...` + ) + + watchItems(componentRootPath, writeComponentFactory) +} + +/** + * Generates the component factory file and saves it to the filesystem. + * By convention, we expect to find React components under src/components/** (subfolders are + * searched recursively). The filename, with the extension stripped, is used for the component's + * string name (for mapping to Sitecore). The filename, with extension and non-word characters + * stripped, is used to identify the component's JavaScript module definition (for initializing + * new component instances in code). + * Modify this function to use a different convention. + */ +function writeComponentFactory() { + /** + * You can specify components which you want to import from external/internal packages + * in format: + * { + * name: 'package name', + * components: [ + * { + * componentName: 'component name', // component rendering name, + * moduleName: 'module name' // component name to import from the package + * } + * ] + * } + */ + const packages: PackageDefinition[] = [] + const components = getComponentList(componentRootPath) + + components.unshift(...packages) + + const fileContent = generateComponentFactory(components) + console.log(`Writing component factory to ${componentFactoryPath}`) + fs.writeFileSync(componentFactoryPath, fileContent, { + encoding: 'utf8', + }) +} + +function getComponentList(path: string): (PackageDefinition | ComponentFile)[] { + const components = getItems({ + path, + resolveItem: (path, name) => ({ + path: `${path}/${name}`, + componentName: name, + moduleName: name.replace(/[^\w]+/g, ''), + }), + cb: (name) => console.debug(`Registering JSS component ${name}`), + }) + + return components +} diff --git a/examples/cms-sitecore-xmcloud/scripts/generate-config.ts b/examples/cms-sitecore-xmcloud/scripts/generate-config.ts new file mode 100644 index 0000000000000..cabc98dc67fdf --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/generate-config.ts @@ -0,0 +1,63 @@ +import 'dotenv/config' +import fs from 'fs' +import path from 'path' +import { constantCase } from 'constant-case' +import { JssConfig, jssConfigFactory } from './config' + +/* + CONFIG GENERATION + Generates the /src/temp/config.js file which contains runtime configuration + that the app can import and use. +*/ + +const defaultConfig: JssConfig = { + sitecoreApiKey: process.env[`${constantCase('sitecoreApiKey')}`], + sitecoreApiHost: process.env[`${constantCase('sitecoreApiHost')}`], + jssAppName: process.env[`${constantCase('jssAppName')}`], + graphQLEndpointPath: process.env[`${constantCase('graphQLEndpointPath')}`], + defaultLanguage: process.env[`${constantCase('defaultLanguage')}`], + graphQLEndpoint: process.env[`${constantCase('graphQLEndpoint')}`], +} + +generateConfig(defaultConfig) + +/** + * Generates the JSS config based on config plugins (under ./config/plugins) + * and then writes the config to disk. + * @param {JssConfig} defaultConfig Default configuration. + */ +function generateConfig(defaultConfig: JssConfig): void { + jssConfigFactory + .create(defaultConfig) + .then((config) => { + writeConfig(config) + }) + .catch((e) => { + console.error('Error generating config') + console.error(e) + process.exit(1) + }) +} + +/** + * Writes the config object to disk with support for environment variables. + * @param {JssConfig} config JSS configuration to write. + */ +function writeConfig(config: JssConfig): void { + let configText = `/* eslint-disable */ +// Do not edit this file, it is auto-generated at build time! +// See scripts/bootstrap.ts to modify the generation of this file. +const config = {};\n` + + // Set configuration values, allowing override with environment variables + Object.keys(config).forEach((prop) => { + configText += `config.${prop} = process.env.${constantCase(prop)} || '${ + config[prop] + }',\n` + }) + configText += `module.exports = config;` + + const configPath = path.resolve('src/temp/config.js') + console.log(`Writing runtime config to ${configPath}`) + fs.writeFileSync(configPath, configText, { encoding: 'utf8' }) +} diff --git a/examples/cms-sitecore-xmcloud/scripts/generate-plugins.ts b/examples/cms-sitecore-xmcloud/scripts/generate-plugins.ts new file mode 100644 index 0000000000000..c63711ef5621e --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/generate-plugins.ts @@ -0,0 +1,138 @@ +import fs from 'fs' +import path from 'path' +import { getItems } from './utils' + +/* + PLUGINS GENERATION + NOTE: pluginName: the name of the plugin in the src/lib folder + Generates the `/src/temp/{pluginName}-plugins.ts` file, which exports list of plugins + + Generating the plugins is optional, and it can be maintained manually if preferred. + + The default convention uses the plugin's filename (without the extension) as the first part of the component + name. For example, the file `/lib/page-props-factory/plugins/exampleName.ts` would map to plugin `exampleNamePlugin`. + This can be customized in writePlugins(). +*/ + +enum ModuleType { + CJS, + ESM, +} + +interface PluginDefinition { + listPath: string + rootPath: string + moduleType: ModuleType +} + +interface PluginFile { + path: string + name: string +} + +const pluginDefinitions = [ + { + listPath: 'scripts/temp/config-plugins.ts', + rootPath: 'scripts/config/plugins', + moduleType: ModuleType.ESM, + }, + { + listPath: 'src/temp/sitemap-fetcher-plugins.ts', + rootPath: 'src/lib/sitemap-fetcher/plugins', + moduleType: ModuleType.ESM, + }, + { + listPath: 'src/temp/middleware-plugins.ts', + rootPath: 'src/lib/middleware/plugins', + moduleType: ModuleType.ESM, + }, + { + listPath: 'src/temp/page-props-factory-plugins.ts', + rootPath: 'src/lib/page-props-factory/plugins', + moduleType: ModuleType.ESM, + }, + { + listPath: 'src/temp/next-config-plugins.js', + rootPath: 'src/lib/next-config/plugins', + moduleType: ModuleType.CJS, + }, + { + listPath: 'src/temp/extract-path-plugins.ts', + rootPath: 'src/lib/extract-path/plugins', + moduleType: ModuleType.ESM, + }, + { + listPath: 'src/temp/site-resolver-plugins.ts', + rootPath: 'src/lib/site-resolver/plugins', + moduleType: ModuleType.ESM, + }, +] + +run(pluginDefinitions) + +function run(definitions: PluginDefinition[]) { + definitions.forEach((definition) => { + writePlugins( + definition.listPath, + definition.rootPath, + definition.moduleType + ) + }) +} + +/** + * Generates the plugins file and saves it to the filesystem. + * By convention, we expect to find plugins under src/lib/{pluginName}/plugins/** (subfolders are + * searched recursively). The filename, with extension and non-word characters + * stripped, is used to identify the plugin's JavaScript module definition (for adding + * new plugin to the factory). + * Modify this function to use a different convention. + */ +function writePlugins( + listPath: string, + rootPath: string, + moduleType: ModuleType +) { + const segments = rootPath.split('/') + const pluginName = segments[segments.length - 2] + const plugins = getPluginList(rootPath, pluginName) + let fileContent = '' + + fileContent = plugins + .map((plugin) => { + return moduleType === ModuleType.CJS + ? `exports.${plugin.name} = require('${plugin.path.replace( + 'src/', + '../' + )}');` + : `export { ${plugin.name} } from '${plugin.path}';` + }) + .join('\r\n') + .concat('\r\n') + + if (!plugins.length) { + fileContent = + moduleType === ModuleType.CJS + ? 'module.exports = {};\r\n' + : 'export {};\r\n' + } + + const filePath = path.resolve(listPath) + console.log(`Writing ${pluginName} plugins to ${filePath}`) + fs.writeFileSync(filePath, fileContent, { + encoding: 'utf8', + }) +} + +function getPluginList(path: string, pluginName: string): PluginFile[] { + const plugins = getItems({ + path, + resolveItem: (path, name) => ({ + path: `${path}/${name}`, + name: `${name.replace(/-./g, (x) => x[1].toUpperCase())}Plugin`, + }), + cb: (name) => console.debug(`Registering ${pluginName} plugin ${name}`), + }) + + return plugins +} diff --git a/examples/cms-sitecore-xmcloud/scripts/scaffold-component.ts b/examples/cms-sitecore-xmcloud/scripts/scaffold-component.ts new file mode 100644 index 0000000000000..4a11b535e18a3 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/scaffold-component.ts @@ -0,0 +1,95 @@ +/* + Component Scaffolding Script + This is a script that enables scaffolding a new JSS component using `jss scaffold `. + The default convention is that component names must start with a capital letter, and can contain + letters, number, underscores, or dashes. + + If the parameter includes a path, it must be relative to the src/components folder. + For example, `jss scaffold search/SearchBox` will create a component called `SearchBox` in + `src/components/search/SearchBox.tsx`. Specifying a relative path is optional, and just providing + the name is ok. + + Edit this script if you wish to use your own conventions for component storage in your JSS app. +*/ + +/* eslint-disable no-throw-literal,no-console */ + +import fs from 'fs' +import path from 'path' +import chalk from 'chalk' +import generateComponentSrc from './templates/component-src' + +const componentRootPath = 'src/components' + +// Matches component names that start with a capital letter, and contain only letters, number, +// underscores, or dashes. Optionally, the component name can be preceded by a relative path +const nameParamFormat = new RegExp(/^((?:[\w-]+\/)*)([A-Z][\w-]+)$/) +const componentArg = process.argv[2] + +if (!componentArg) { + throw 'Component name was not passed. Usage: jss scaffold ' +} + +const regExResult = nameParamFormat.exec(componentArg) + +if (regExResult === null) { + throw `Component name should start with an uppercase letter and contain only letters, numbers, +dashes, or underscores. If specifying a path, it must be relative to src/components` +} + +const componentPath = regExResult[1] +const componentName = regExResult[2] +const filename = `${componentName}.tsx` + +const componentOutputPath = scaffoldFile( + componentRootPath, + generateComponentSrc(componentName), + filename +) + +console.log( + chalk.green(` +Scaffolding of ${componentName} complete. +Next steps:`) +) + +if (componentOutputPath) { + console.log( + `* Implement the React component in ${chalk.green(componentOutputPath)}` + ) +} + +/** + * Force to use `crlf` line endings, we are using `crlf` across the project. + * Replace: `lf` (\n), `cr` (\r) + * @param {string} content + */ +function editLineEndings(content: string) { + return content.replace(/\r|\n/gm, '\r\n') +} + +/** + * Creates a file relative to the specified path if the file doesn't exist. Creates directories as needed. + * @param {string} rootPath - the root path + * @param {string} fileContent - the file content + * @param {string} filename - the filename + * @returns the new file's filepath + */ +function scaffoldFile( + rootPath: string, + fileContent: string, + filename: string +): string | null { + const outputDir = path.join(rootPath, componentPath) + const outputFile = path.join(outputDir, filename) + + if (fs.existsSync(outputFile)) { + console.log(chalk.red(`Skipping creating ${outputFile}; already exists.`)) + return null + } + + fs.mkdirSync(outputDir, { recursive: true }) + fs.writeFileSync(outputFile, editLineEndings(fileContent), 'utf8') + console.log(chalk.green(`File ${outputFile} has been scaffolded.`)) + return outputFile +} diff --git a/examples/cms-sitecore-xmcloud/scripts/temp/.npmignore b/examples/cms-sitecore-xmcloud/scripts/temp/.npmignore new file mode 100644 index 0000000000000..d6b7ef32c8478 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/temp/.npmignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/examples/cms-sitecore-xmcloud/scripts/temp/config-plugins.ts b/examples/cms-sitecore-xmcloud/scripts/temp/config-plugins.ts new file mode 100644 index 0000000000000..aacc0009fad84 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/temp/config-plugins.ts @@ -0,0 +1,4 @@ +export { computedPlugin } from 'scripts/config/plugins/computed' +export { fallbackPlugin } from 'scripts/config/plugins/fallback' +export { packageJsonPlugin } from 'scripts/config/plugins/package-json' +export { scjssconfigPlugin } from 'scripts/config/plugins/scjssconfig' diff --git a/examples/cms-sitecore-xmcloud/scripts/templates/component-factory.ts b/examples/cms-sitecore-xmcloud/scripts/templates/component-factory.ts new file mode 100644 index 0000000000000..63cc562fc9e0d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/templates/component-factory.ts @@ -0,0 +1,142 @@ +/** + * Describes a file that represents a component definition + */ +export interface ComponentFile { + path: string + moduleName: string + componentName: string +} + +export interface PackageDefinition { + name: string + components: { + moduleName: string + componentName: string + }[] +} + +const isLazyLoadingModule = (componentPath: string) => + componentPath.includes('.dynamic') + +const removeDynamicModuleNameEnding = (moduleName: string) => + moduleName.replace(/\.?dynamic$/i, '') + +/** + * Generates the contents of the component factory file using a predefined string template. + * @param components - the list of component files to include + * @returns component factory file contents + */ +function generateComponentFactory( + components: (PackageDefinition | ComponentFile)[] +): string { + const componentFiles = components.filter( + (component) => (component as ComponentFile).path + ) as ComponentFile[] + const packages = components.filter( + (component) => (component as PackageDefinition).components + ) as PackageDefinition[] + + const hasLazyModules = componentFiles.find((component) => + isLazyLoadingModule(component.path) + ) + + return `/* eslint-disable */ +// Do not edit this file, it is auto-generated at build time! +// See scripts/generate-component-factory.ts to modify the generation of this file. + +${hasLazyModules ? "import dynamic from 'next/dynamic'" : ''} + +${packages.map((pkg) => { + const list = pkg.components.map((c) => c.moduleName).join(', ') + + return `import { ${list} } from '${pkg.name}'` +})} +${componentFiles + .map((component) => { + if (isLazyLoadingModule(component.path)) { + const moduleName = removeDynamicModuleNameEnding(component.moduleName) + return `const ${moduleName} = { + module: () => import('${component.path}'), + element: (isEditing?: boolean) => isEditing ? require('${component.path}')?.default : dynamic(${moduleName}.module) +}` + } + + return `import * as ${component.moduleName} from '${component.path}';` + }) + .join('\n')} + +const components = new Map(); +${packages.map((p) => + p.components.map( + (component) => + `components.set('${component.componentName}', ${component.moduleName})` + ) +)} +${componentFiles + .map( + (component) => + `components.set('${ + isLazyLoadingModule(component.path) + ? removeDynamicModuleNameEnding(component.componentName) + : component.componentName + }', ${ + isLazyLoadingModule(component.path) + ? removeDynamicModuleNameEnding(component.moduleName) + : component.moduleName + });` + ) + .join('\n')} + +// Next.js 'dynamic' import and JavaScript 'dynamic' import are different. +// Next.js 'dynamic(...)' returns common 'React.ComponentType' while +// 'import('...')' returns 'Promise' that will resolve module. +// componentModule uses 'import(...)' because primary usage of it to get not only 'React Component' (default export) but all named exports. +// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports +// componentFactory uses 'dynamic(...)' because primary usage of it to render 'React Component' (default export). +// See https://nextjs.org/docs/advanced-features/dynamic-import +// At the end you will have single preloaded script for each lazy loading module. +// Editing mode doesn't work well with dynamic components in nextjs: dynamic components are not displayed without refresh after a rendering is added. +// This happens beacuse Sitecore editors simply insert updated HTML generated on server side. This conflicts with nextjs dynamic logic as no HTML gets rendered for dynamic component +// So we use require() to obtain dynamic components in editing mode while preserving dynamic logic for non-editing scenarios +// As we need to be able to seamlessly work with dynamic components in both editing and normal modes, different componentFactory functions will be passed to app + +export function componentModule(componentName: string) { + const component = components.get(componentName); + + // check that component is lazy loading module + if (!component?.default && component?.module) { + // return js dynamic import + return component.module(); + } + + return component; +} + +function baseComponentFactory(componentName: string, exportName?: string, isEditing?: boolean) { + const DEFAULT_EXPORT_NAME = 'Default'; + const component = components.get(componentName); + + // check that component should be dynamically imported + if (component?.element) { + // return next.js dynamic import + return component.element(isEditing); + } + + if (exportName && exportName !== DEFAULT_EXPORT_NAME) { + return component[exportName]; + } + + return component?.Default || component?.default || component; +} + +export function componentFactory(componentName: string, exportName?: string) { + return baseComponentFactory(componentName, exportName, false); +} + +export function editingComponentFactory(componentName: string, exportName?: string) { + return baseComponentFactory(componentName, exportName, true); +} +` +} + +export default generateComponentFactory diff --git a/examples/cms-sitecore-xmcloud/scripts/templates/component-src.ts b/examples/cms-sitecore-xmcloud/scripts/templates/component-src.ts new file mode 100644 index 0000000000000..9adae12a29c11 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/templates/component-src.ts @@ -0,0 +1,27 @@ +/** + * Generates React boilerplate for a component under `src/components` + * @param componentName - the component name + * @returns component src boilerplate as a string + */ +function generateComponentSrc(componentName: string): string { + return `import { Text, Field, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs'; +import { ComponentProps } from 'lib/component-props'; + +type ${componentName}Props = ComponentProps & { + fields: { + heading: Field; + }; +}; + +const ${componentName} = (props: ${componentName}Props): JSX.Element => ( +
+

${componentName} Component

+ +
+); + +export default withDatasourceCheck()<${componentName}Props>(${componentName}); +` +} + +export default generateComponentSrc diff --git a/examples/cms-sitecore-xmcloud/scripts/utils.ts b/examples/cms-sitecore-xmcloud/scripts/utils.ts new file mode 100644 index 0000000000000..ab9e496f5b67d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/scripts/utils.ts @@ -0,0 +1,64 @@ +import fs from 'fs' +import chokidar from 'chokidar' + +/** + * Run watch mode, watching on @var rootPath + */ +export function watchItems(rootPath: string, cb: () => void): void { + chokidar + .watch(rootPath, { ignoreInitial: true, awaitWriteFinish: true }) + .on('add', cb) + .on('unlink', cb) +} + +/** + * Using @var path find all files recursively and generate output using @var resolveItem by calling it for each file + * @param path plugins path + * @param resolveItem will resolve item in required data format + * @param cb will be called when new item is found + * @param fileFormat Matches specific files + * @returns {Item[]} items + */ +export function getItems(settings: { + path: string + resolveItem: (path: string, name: string) => Item + cb?: (name: string) => void + fileFormat?: RegExp +}): Item[] { + const { + path, + resolveItem, + cb, + fileFormat = new RegExp(/(.+)(? { + if (item.isDirectory()) { + folders.push(item) + } + + if (fileFormat.test(item.name)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const name = item.name.match(fileFormat)![1] + items.push(resolveItem(path, name)) + cb && cb(name) + } + }) + + for (const folder of folders) { + items.push( + ...getItems({ + path: `${path}/${folder.name}`, + resolveItem, + cb, + fileFormat, + }) + ) + } + + return items +} diff --git a/examples/cms-sitecore-xmcloud/sitecore/config/xmcloud-nextjs-starter.config b/examples/cms-sitecore-xmcloud/sitecore/config/xmcloud-nextjs-starter.config new file mode 100644 index 0000000000000..e0a7e02d4a43f --- /dev/null +++ b/examples/cms-sitecore-xmcloud/sitecore/config/xmcloud-nextjs-starter.config @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + mw=100,mh=50 + + + mw=16 + mw=32 + mw=48 + mw=64 + mw=96 + mw=128 + mw=256 + mw=384 + mw=640 + mw=750 + mw=828 + mw=1080 + mw=1200 + mw=1920 + mw=2048 + mw=3840 + + + + + + + + + + false + + + + + + + false + + + + + + + diff --git a/examples/cms-sitecore-xmcloud/src/Layout.tsx b/examples/cms-sitecore-xmcloud/src/Layout.tsx new file mode 100644 index 0000000000000..42f6d7e765fc6 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/Layout.tsx @@ -0,0 +1,63 @@ +/** + * This Layout is needed for Starter Kit. + */ +import React from 'react' +import Head from 'next/head' +import { + Placeholder, + getPublicUrl, + LayoutServiceData, + Field, +} from '@sitecore-jss/sitecore-jss-nextjs' +import Scripts from 'src/Scripts' + +// Prefix public assets with a public URL to enable compatibility with Sitecore Experience Editor. +// If you're not supporting the Experience Editor, you can remove this. +const publicUrl = getPublicUrl() + +interface LayoutProps { + layoutData: LayoutServiceData +} + +interface RouteFields { + [key: string]: unknown + Title?: Field +} + +const Layout = ({ layoutData }: LayoutProps): JSX.Element => { + const { route } = layoutData.sitecore + const fields = route?.fields as RouteFields + const isPageEditing = layoutData.sitecore.context.pageEditing + const mainClassPageEditing = isPageEditing ? 'editing-mode' : 'prod-mode' + + return ( + <> + + + {fields?.Title?.value?.toString() || 'Page'} + + + + {/* root placeholder for the app, which we add components to using route data */} +
+
+ +
+
+
+ {route && } +
+
+
+ +
+
+ + ) +} + +export default Layout diff --git a/examples/cms-sitecore-xmcloud/src/Navigation.tsx b/examples/cms-sitecore-xmcloud/src/Navigation.tsx new file mode 100644 index 0000000000000..c1e7a1446f617 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/Navigation.tsx @@ -0,0 +1,27 @@ +import { getPublicUrl } from '@sitecore-jss/sitecore-jss-nextjs' + +// Prefix public assets with a public URL to enable compatibility with Sitecore editors. +// If you're not supporting Sitecore editors, you can remove this. +const publicUrl = getPublicUrl() + +const Navigation = (): JSX.Element => ( +
+ +
+) + +export default Navigation diff --git a/examples/cms-sitecore-xmcloud/src/NotFound.tsx b/examples/cms-sitecore-xmcloud/src/NotFound.tsx new file mode 100644 index 0000000000000..e4e59d16b6e3c --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/NotFound.tsx @@ -0,0 +1,19 @@ +import Head from 'next/head' + +/** + * Rendered in case if we have 404 error + */ +const NotFound = (): JSX.Element => ( + <> + + 404: NotFound + +
+

Page not found

+

This page does not exist.

+ Go to the Home page +
+ +) + +export default NotFound diff --git a/examples/cms-sitecore-xmcloud/src/Scripts.tsx b/examples/cms-sitecore-xmcloud/src/Scripts.tsx new file mode 100644 index 0000000000000..c57b322012fde --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/Scripts.tsx @@ -0,0 +1,5 @@ +const Scripts = (): JSX.Element | null => { + return null +} + +export default Scripts diff --git a/examples/cms-sitecore-xmcloud/src/assets/app.css b/examples/cms-sitecore-xmcloud/src/assets/app.css new file mode 100644 index 0000000000000..489cdc72b0b2d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/app.css @@ -0,0 +1,39 @@ +a[target='_blank']:after { + content: '\1F5D7'; +} + +/* + Hides Sitecore editor markup, + if you run the app in connected mode while the Sitecore cookies + are set to edit mode. +*/ +.scChromeData, +.scpm { + display: none !important; +} + +/* + Styles for default JSS error components +*/ +.sc-jss-editing-error, +.sc-jss-placeholder-error { + padding: 1em; + background-color: lightyellow; +} + +/* + Style for default content block +*/ +.contentTitle { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.2; +} + +a { + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_component.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_component.scss new file mode 100644 index 0000000000000..6081809a40dee --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_component.scss @@ -0,0 +1,18 @@ +.component-content { + @include respond-to(mobile-large) { + .row { + padding: 0; + margin: 0; + } + } +} +@include respond-to(mobile-large) { + .row { + margin: 0; + padding: 0; + > * { + padding: 0; + margin: 0; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_container.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_container.scss new file mode 100644 index 0000000000000..8644503433da7 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_container.scss @@ -0,0 +1,79 @@ +@import '@sass/abstracts/mixins'; +@import 'variables'; + +body { + font-family: Roboto; + color: $main-color; +} + +@media (min-width: 1400px) { + .container { + max-width: 1250px; + } +} + +/**** START STYLE MAX HEIGHT ****/ +.prod-mode { + display: flex; + flex-direction: column; + height: 100vh; + + main { + flex: 1 0 auto; + } + + footer { + flex-shrink: 0; + } +} +/**** END STYLE MAX HEIGHT ****/ + +main { + .main-header { + margin-top: 55px; + margin-bottom: 30px; + + @include respond-to(mobile-large) { + margin-bottom: 0; + } + + h4 { + font-size: $text-size-50; + font-weight: 500; + line-height: 70px; + } + } + + .main-news-header { + margin-top: 60px; + + h2 { + font-size: $text-size-36; + line-height: 43px; + } + } + + @include respond-to(mobile-large) { + padding-top: 0; + margin-bottom: 0; + + .main-header { + margin-top: 10px; + + h4 { + font-size: $text-size-24; + line-height: 32px; + } + } + + .main-news-header { + padding-bottom: 35px; + + h2 { + margin-top: 0; + font-size: $text-size-18; + line-height: 22px; + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_fonts.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_fonts.scss new file mode 100644 index 0000000000000..d383a9572f687 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_fonts.scss @@ -0,0 +1 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_footer.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_footer.scss new file mode 100644 index 0000000000000..bc97d5ce85074 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_footer.scss @@ -0,0 +1,32 @@ +@import '@sass/abstracts/mixins'; +@import 'variables'; + +footer { + @include respond-to(mobile-large) { + padding-top: 0; + } + .container-dark-background { + background-color: #262626; + } + + .contacts { + font-size: $text-size-14; + + a { + color: $text-white; + } + + p, + span { + color: $text-white; + } + } + + .indent-inner { + padding: 65px; + + @include respond-to(mobile-large) { + padding: 40px 0; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_header.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_header.scss new file mode 100644 index 0000000000000..e5810fee4a454 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_header.scss @@ -0,0 +1,49 @@ +@import '@sass/abstracts/vars/colors'; +@import '@sass/abstracts/mixins'; +@import 'variables'; + +.prod-mode { + #header { + display: flex; + + @include respond-to(mobile-large) { + padding-bottom: 0; + flex-direction: column-reverse; + } + } +} + +header { + #header { + .bs-title { + padding-left: 50px; + + h1 { + font-size: $text-size-24; + font-weight: 600; + line-height: 18px; + padding-top: 40px; + margin: 0; + } + } + + @include respond-to(mobile-large) { + padding-bottom: 0; + padding-top: 0; + flex-direction: column-reverse; + + .bs-title { + padding-left: 0; + text-align: center; + margin-top: -5px; + + h1 { + font-weight: 500; + line-height: 29px; + padding-top: 0; + margin-bottom: 10px; + } + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_navigation.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_navigation.scss new file mode 100644 index 0000000000000..43e7ef89ff932 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_navigation.scss @@ -0,0 +1,152 @@ +@import '@sass/abstracts/vars'; +@import 'variables'; + +$hamburger-width: 28px; +$hamburger-height: 18px; +$border-size: 6px; +$hamburger-margin: 18px; + +.navigation { + .menu-mobile-navigate-wrapper { + width: 100%; + } +} + +.navigation.navigation-horizontal { + width: 100%; + padding-right: 70px; + margin-top: -15px; + + .menu-mobile-navigate { + display: none; + } + + @include respond-to(mobile-large) { + padding-right: 0; + } + + .component-content { + display: inline-block; + + @include respond-to(mobile-large) { + display: none; + } + + ul.clearfix { + list-style: none; + } + .level0 { + display: flex; + } + + .level0, + .level1 { + float: left; + margin-left: 30px; + + > .navigation-title { + > a { + border-width: 0; + font-size: $text-size-14; + font-weight: 400; + } + } + } + } + + @include respond-to(mobile-large) { + .component-content { + display: none; + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 0; + background-color: $bg-black-active; + z-index: 1; + + * { + text-align: center !important; + } + + nav { + padding-top: 110px; + + .level0 { + display: block; + } + } + + ul { + margin: 0; + padding: 0; + } + + .level0, + .level1 { + float: unset; + margin-left: 0; + > .navigation-title { + > a { + font-size: $text-size-30; + line-height: 90px; + > span { + color: $text-white; + } + } + } + } + } + + .menu-mobile-navigate-wrapper { + .menu-mobile-navigate { + display: inline-block; + z-index: 2; + position: absolute; + right: $hamburger-margin; + top: $hamburger-margin; + height: $hamburger-width; + width: $hamburger-width; + opacity: 0; + + &:checked ~ { + .menu-humburger { + &::before { + content: '\00d7'; + color: $text-basic-active; + font-size: $text-size-48; + position: fixed; + top: 0; + right: 0; + margin-top: calc($hamburger-margin + ($hamburger-margin / 2)); + margin-right: $hamburger-margin; + line-height: 0; + border: 0; + } + } + + .component-content { + position: fixed; + display: inline-block; + } + } + } + + .menu-humburger { + &::before { + content: ''; + width: $hamburger-width; + height: $hamburger-height; + margin-right: $hamburger-margin; + margin-top: calc($hamburger-margin + ($hamburger-margin / 2)) + 8px; + display: block; + border-top: 6px solid $bg-black; + border-bottom: 6px solid $bg-black; + float: right; + z-index: 99; + cursor: pointer; + } + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_promo.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_promo.scss new file mode 100644 index 0000000000000..255b26c9b3d95 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_promo.scss @@ -0,0 +1,58 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; +/**PROMO**/ + +.promo { + &.main-promo-no-border { + padding-left: 0; + padding-right: 0; + padding-bottom: 0; + margin-bottom: 80px; + + @include respond-to(mobile-large) { + margin-bottom: 0; + } + + > .component-content { + border: 0; + max-width: 583px; + margin-right: 50px; + + > div { + padding-bottom: 0; + } + + @include respond-to(mobile-large) { + max-width: 100%; + margin-right: 0; + } + + .promo-text { + .field-promotext { + font-size: 14px; + + h3 { + font-size: $text-size-18; + margin: 15px 0; + + @include respond-to(mobile-large) { + margin: 10px 0; + } + } + p { + margin: 10px 0; + } + } + } + @include respond-to(mobile-large) { + > div { + padding: 0; + } + + .promo-text { + padding: 15px 30px 5px 30px; + } + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_rich-text.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_rich-text.scss new file mode 100644 index 0000000000000..ae6878e5a0ce8 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_rich-text.scss @@ -0,0 +1,11 @@ +@import '@sass/abstracts/vars'; +@import 'variables'; + +.rich-text { + font-size: $text-size-16; + + @include respond-to(mobile-large) { + padding: 0 30px 10px 30px; + font-size: $text-size-14; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/_variables.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/_variables.scss new file mode 100644 index 0000000000000..ad4c5f8bc79f6 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/_variables.scss @@ -0,0 +1,10 @@ +$text-size-14: 14px; +$text-size-16: 16px; +$text-size-18: 18px; +$text-size-24: 24px; +$text-size-30: 30px; +$text-size-36: 36px; +$text-size-48: 48px; +$text-size-50: 50px; + +$main-color: #27272a; diff --git a/examples/cms-sitecore-xmcloud/src/assets/basic/main.scss b/examples/cms-sitecore-xmcloud/src/assets/basic/main.scss new file mode 100644 index 0000000000000..2ce2e49be80e5 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/basic/main.scss @@ -0,0 +1,8 @@ +@import 'fonts'; +@import 'container'; +@import 'header'; +@import 'promo'; +@import 'navigation'; +@import 'component'; +@import 'rich-text'; +@import 'footer'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/main.scss b/examples/cms-sitecore-xmcloud/src/assets/main.scss new file mode 100644 index 0000000000000..addfe5ca592e7 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/main.scss @@ -0,0 +1,5 @@ +@import 'basic/fonts'; +@import 'font-awesome/scss/font-awesome'; +@import 'bootstrap/scss/bootstrap'; +@import 'sass/main.scss'; +@import 'basic/main.scss'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/_app.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/_app.scss new file mode 100644 index 0000000000000..10ba4ad39b1c0 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/_app.scss @@ -0,0 +1,105 @@ +html { + font-size: 62.5%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + margin-bottom: 0px; + height: auto !important; +} + +body { + @include opensans-font-stack(); + position: relative; + overflow: auto; + color: $text-basic; + font-size: 16px; + line-height: 1.5; + background: $page-bg; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + height: auto !important; + &.on-page-editor { + background: $page-bg-editor !important; + } +} + +a { + color: $text-basic; + cursor: pointer; + font-size: 0.85em; + &:hover { + color: $text-basic-active; + } +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: bold; +} + +h1 { + font-size: 2em; +} + +h2 { + font-size: 1.5em; +} + +h3 { + font-size: 1.2em; +} + +h4 { + font-size: 1em; +} + +h5 { + font-size: 0.83em; +} + +h6 { + font-size: 0.67em; +} + +ul li { + list-style-type: none; +} + +.xa-variable { + border: 0px; + padding: 1px; + margin: 0px; + background-color: #ebebe4; + color: #545454; + user-select: none; + pointer-events: none; +} + +//Navigation Bar fix +#breadcrumbMenuSubcontrol_context_menu * { + box-sizing: initial; +} + +//End navigation bar fix +.menu-mobile-navigate { + display: none; +} + +#header, +#content, +#footer, +.sc-jss-empty-placeholder { + width: 100%; + display: flex; + flex-wrap: wrap; +} + +.sc-jss-placeholder-error { + background: #ff0000; + outline: 5px solid #e36565; + padding: 10px; + color: #fff; + max-width: 500px; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_functions.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_functions.scss new file mode 100644 index 0000000000000..fdef2da81ddb1 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_functions.scss @@ -0,0 +1,7 @@ +@function headings($from: 1, $to: 6) { + @if $from==$to { + @return 'h#{$from}'; + } @else { + @return 'h#{$from},' + headings($from + 1, $to); + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_mixins.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_mixins.scss new file mode 100644 index 0000000000000..b6be54ed08466 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_mixins.scss @@ -0,0 +1,121 @@ +@import 'vars'; + +/* breakpoints */ + +$break-desktop: 1100px; +$break-mobile: 380px; +$break-mobile-horizontal: 640px; +$break-mobile-large: 992px; +@mixin wrapper() { + max-width: 960px; + margin: 0 auto !important; +} +@mixin clearfix { + &:after { + content: ''; + display: table; + clear: both; + } +} +@mixin headings($from: 1, $to: 6) { + @for $i from $from through $to { + h#{$i} { + @content; + } + } +} +@mixin font-size($sizeValue: 1.6) { + font-size: ($sizeValue * 10) + px; + font-size: $sizeValue + rem; +} +@mixin proxima-font($weight: semibold) { + @if ($weight==semibold) { + font-family: 'ProximaNova-Semibold', arial, helvetica, sans-serif; + } @else if($weight==light) { + font-family: 'ProximaNova-Light', arial, helvetica, sans-serif; + } +} +@mixin opensans-font-stack() { + font-family: 'Open Sans', Helvetica, Verdana, Tahoma, sans-serif; +} +@mixin loading-gif() { + background-image: url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiBmaWxsPSJibGFjayI+DQogIDxwYXRoICBvcGFjaXR5PSIuMjUiIGQ9Ik0xNiAwIEExNiAxNiAwIDAgMCAxNiAzMiBBMTYgMTYgMCAwIDAgMTYgMCBNMTYgNCBBMTIgMTIgMCAwIDEgMTYgMjggQTEyIDEyIDAgMCAxIDE2IDQiLz4NCiAgPHBhdGggZmlsbD0nIzFhODBiNicgZD0iTTE2IDAgQTE2IDE2IDAgMCAxIDMyIDE2IEwyOCAxNiBBMTIgMTIgMCAwIDAgMTYgNHoiPg0KICAgIDxhbmltYXRlVHJhbnNmb3JtIGF0dHJpYnV0ZU5hbWU9InRyYW5zZm9ybSIgdHlwZT0icm90YXRlIiBmcm9tPSIwIDE2IDE2IiB0bz0iMzYwIDE2IDE2IiBkdXI9IjAuOHMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiAvPg0KICA8L3BhdGg+DQo8L3N2Zz4NCg==); + background-position: center center; + background-repeat: no-repeat; +} +@mixin respond-to($media) { + @if $media==mobile { + @media only screen and (max-width: $break-mobile) { + @content; + } + } @else if $media==mobile-horizontal { + @media only screen and (max-width: $break-mobile-horizontal - 1) { + @content; + } + } @else if $media==mobile-large { + @media only screen and (max-width: $break-mobile-large) { + @content; + } + } @else if $media==tablet { + @media only screen and (min-width: $break-mobile + 1) and (max-width: $break-desktop - 1) { + @content; + } + } @else if $media==all-mobile { + @media only screen and (max-width: $break-desktop - 1) { + @content; + } + } @else if $media==desktop { + @media only screen and (min-width: $break-desktop) { + @content; + } + } +} +@mixin border-basic( + $position: all, + $border-color: $border-gray, + $border-width: 1px +) { + @if ($position!=all) { + border-#{$position}-width: $border-width; + border-#{$position}-style: solid; + border-#{$position}-color: $border-color; + } @else { + border-width: $border-width; + border-style: solid; + border-color: $border-color; + } +} +@mixin fixed-bg($pos, $min-height: 240px) { + background-position: $pos; + background-attachment: fixed; + min-height: $min-height; +} +@mixin linear-gradient($direction, $color-stops...) { + // Direction has been omitted and happens to be a color-stop + @if is-direction($direction) ==false { + $color-stops: $direction, $color-stops; + $direction: 180deg; + } + background: nth(nth($color-stops, 1), 1); + background: -webkit-linear-gradient( + legacy-direction($direction), + $color-stops + ); + background: linear-gradient($direction, $color-stops); +} +@mixin default-link-button { + @include border-basic(); + @include font-size(1.2); + display: inline-block; + vertical-align: middle; + box-sizing: border-box; + margin: 5px 0; + padding: 10px 15px; + text-align: center; + text-decoration: none; + font-weight: bold; + &:hover { + color: $text-basic; + background: $bg-light-gray; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_vars.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_vars.scss new file mode 100644 index 0000000000000..c3c1d94e358d0 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/_vars.scss @@ -0,0 +1,3 @@ +@import 'vars/colors'; +@import 'vars/margins'; +@import 'vars/fontSizes'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_colors.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_colors.scss new file mode 100644 index 0000000000000..c7b73f40c87e1 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_colors.scss @@ -0,0 +1,283 @@ +//Backgrounds colors +$bg-transparent: transparent !default; +$bg-basic-color: #ffffff !default; +$bg-basic-color-active: #cccccc !default; +$bg-light-gray: #f7f7f7 !default; +$bg-light-gray-active: #dadada !default; +$bg-blue: #89c6cc; +$bg-blue-active: #15909c !default; +$bg-submenu: #edebeb !default; +$bg-submenu-active: #f6f6f6 !default; +$bg-black: #000; +$bg-black-active: #3d3d3d; +$bg-dark-gray: #262626; +//Text colors +$text-white: #fff !default; +$text-heading-color: #222 !default; +$text-basic: #747474 !default; +$text-basic-active: #878787 !default; +$text-blue: #89c6cc !default; +$text-blue-active: #15909c !default; +$text-submenu-active: #222 !default; +$text-disabled: #aaa !default; +$text-black: #000 !default; +$text-red: #de232f; +$text-gray: #262626; +//Border colors +$border-gray: #d2d2d2 !default; +$border-white: #ffffff !default; +$border-basic-color: #89c6cc !default; +$border-basic-active: #15909c !default; +$border-nav-submenu: #e1e1e1; +//Styles for each component separately +//Accordion +$accordion-header-bg: transparent; +$accordion-header-bg-active: transparent; +$accordion-toggled-bg: transparent; +$accordion-header-border: $border-gray; +//Breadcrumb +$breadcrumb-dropdown-bg: $bg-basic-color; +$breadcrumb-dropdown-bg-active: $bg-blue; +$breadcrumb-dropdown-text-active: $text-white; +$breadcrumb-bg: transparent; +$breadcrumb-color: $text-basic; +$breadcrumb-color-active: $text-blue-active; +//Buttons colors +$btn-green-light: #a0ce4e; +$btn-green: #92be43; +$btn-red-active: #c34e30; +$btn-red: #bc4526; +//Carousel +$carousel-bg: $bg-basic-color; +$carousel-nav: $text-black; +$carousel-nav-active: $text-basic-active; +$carousel-nav-border: $border-basic-color; +//Container component +$container-title-row-bg: $bg-light-gray; +//Event List +$event-list-bg: transparent; +$event-list-item-bg: $bg-basic-color; +$event-list-item-color: $text-basic; +$event-list-title-border: $border-basic-color; +//Calendar +$calendar-bg: $bg-basic-color; +$calendar-header-bg: $bg-basic-color-active; +$calendar-day-color-active: $text-white; +$calendar-title-color: $text-white; +//Feed +$feed-bg: transparent; +$feed-item-bg: transparent; +//Field Editor +$field-editor-bg: transparent; +$field-editor-table-border: $bg-light-gray; +$field-editor-text-header: $text-black; +$field-editor-text-header-active: $text-red; +$field-editor-text: $text-basic; +//File List +$file-list-bg: transparent; +$file-list-item-bg: transparent; +$file-list-title-color: $text-basic; +$file-list-title-border: transparent; +$file-list-item-color: $text-basic; +$file-list-item-color-active: $text-basic-active; +$file-list-item-size: $text-basic; +$file-list-item-borer: $border-basic-color; +$file-list-link-btn-color-active: $text-white; +$file-list-link-btn-color: $text-basic; +$file-list-link-btn-bg: $bg-blue-active; +$file-list-link-btn-bg-active: $bg-blue; +//Flip +$flip-bg: transparent; +$flip-slides-bg: $bg-basic-color; +$flip-slides0-bg: #f6f6f6; +$flip-slides1-bg: $bg-blue-active; +$flip-slides1-color: $text-white; +$flip-border: $border-gray; +//Gallery +$galleria-container-bg: transparent; +$gallery-info-bg: $bg-basic-color; +$gallery-info-border: $border-gray; +$gallery-info-text: $text-basic; +$gallery-nav-active: $text-white; +$gallery-nav: $text-basic; +$gallery-counter-color: $text-white; +//Language selector +$lang-selector-bg: $bg-basic-color; +$lang-selector-border: $border-basic-color; +$lang-selector-item-bg-active: $bg-basic-color; +$lang-selector-item-border: $border-white; +$lang-selector-item-border-active: $border-basic-active; +//Site selector +$site-selector-color: $text-basic; +//Link List +$link-list-bg: transparent; +$link-list-header-border: $border-basic-color; +$link-list-items-bg: transparent; +$link-list-item-bg: transparent; +$link-list-item-color: $text-basic; +$link-list-item-color-active: $text-basic-active; +$link-list-item-border-active: $border-basic-color; +//Login +$login-bg: transparent; +//Logout +$logout-bg: transparent; +$logout-link-text-color: $text-basic; +$logout-link-text-color-active: $text-basic-active; +$logout-link-border: $border-basic-color; +//Map +$map-bg: transparent; +$map-border: none; +//Page List +$page-list-bg: $bg-transparent; +$page-list-item-bg: $bg-transparent; +$page-list-item-title-text: $text-black; +$page-list-item-border: $border-basic-color; +//Pagination +$list-pagination-bg: transparent; +$list-pagination-active-bg: $bg-blue; +$list-pagination-active-color: $text-white; +$list-pagination-active-color: $text-blue; +$list-pagination-active-bg: $bg-submenu-active; +$list-pagination-active-border: $border-basic-active; +//Play list +$play-list-bg: transparent; +$play-list-item-bg: transparent; +$play-list-item-color: $text-basic; +$play-list-item-color-active: $text-white; +$play-list-nav-active: $text-blue; +$play-list-item-bg: $bg-light-gray; +$play-list-item-active-bg: $bg-blue; +$play-list-border: $border-basic-color; +$play-list-title-border: $border-basic-color; +//Promo +$promo-bg: $bg-basic-color; +$promo-bg-hero: rgba(0, 0, 0, 0.5); +$promo-border: $border-gray; +$promo-hero-text-color: $text-white; +$promo-shadow-border: $border-basic-color; +//Rich Text Content +$rich-content-bg: transparent; +$rich-content-color: $text-basic; +$rich-content-border: transparent; +$rich-content-link-color: $text-red; +$rich-content-link-color-active: $text-basic-active; +//Search +$search-filter: $text-basic; +$search-filter-border: $border-basic-color; +//Menu colors +$menu-hover-color: #1b809e; +$menu-active-color: #176f89; +//Navigation +$nav-bg: transparent; +$nav-color-root: $text-basic; +$nav-color-root-active: $text-basic; +$nav-border-root: $border-basic-color; +$nav-border-root-active: $border-basic-color; +$nav-color-submenu: $text-submenu-active; +$nav-color-submenu-active: $text-submenu-active; +$nav-bg-root: $bg-submenu-active; +$nav-bg-submenu: $bg-submenu-active; +$nav-bg-submenu-active: $bg-submenu-active; +$nav-border-submenu: $border-basic-color; +$nav-submenu-item-border: $border-gray; +$nav-submenu-border-active: $border-basic-color; +//Social Media Share +$social-media-share-bg: transparent; +//Tabs +$tab-heading-bg: $bg-light-gray; +$tab-heading-active-bg: $bg-basic-color; +$tab-heading-color: $text-heading-color; +$tab-heading-active-color: $text-black; +$tab-container-bg: transparent; +$tab-container-border: $border-basic-color; +//Title +$title-bg: transparent; +$title-color: $text-basic; +$title-color-active: $text-basic-active; +//Toggle +$toggle-header-bg: $bg-basic-color; +$toggle-content-bg: $bg-basic-color; +$toggle-show-color: $text-basic-active; +//Search Components +$search-btn-bg: transparent; +$search-btn-active-bg: #e0e0e0; +$search-btn-active-border: #adadad; +//Image component +$image-caption-color: $text-basic; +//Media Link Component +$media-link-bg: transparent; +$media-link-border: $border-basic-color; +$media-link-color: $text-basic; +$media-link-color-active: $text-basic-active; +//Tag Component +$tag-color: $text-basic; +$tag-color-active: $text-basic-active; +$tag-border-active: $border-basic-active; +$tag-link-bg: $bg-blue; +$tag-link-bg-active: $bg-blue-active; +$tag-link-color: $text-white; +//Link Component +$link-bg: transparent; +$link-text-color: $text-basic; +$link-text-color-active: $text-basic-active; +$link-border: $border-basic-color; +//Overlay +$overlay-bg: $bg-light-gray; +//Search Components +$search-title-border: $border-basic-color; +$search-title-color: $text-basic; +$search-item-color: $text-basic; +$search-item-color-active: $text-basic; +$search-item-border: $border-basic-color; +$search-item-border-active: $border-basic-active; +// +//Search Facet Summary +$search-facet-summary-border: transparent; +$search-facet-summary-background: transparent; +$search-facet-summary-item-color: $text-basic; +$search-facet-summary-item-color-horizontal: $text-basic; +$search-facet-summary-item-border: $border-gray; +$search-facet-summary-item-border-horizontal: $border-basic-color; +$search-facet-summary-item-shadow: $border-gray; +$search-facet-summary-clear-border-horizontal: $btn-red; +$search-facet-summary-clear-color: $text-red; +$search-facet-summary-clear-color-horizontal: $text-blue; +// +$search-filter-radius-active: $text-blue; +$search-filter-radius-border: $border-gray; +$search-filter-radius-bg: $border-gray; +// +$search-filter-slider-border-active: $border-basic-color; +$search-filter-slider-bg-active: $bg-blue; +$search-filter-slider-btn-border: $border-gray; +$search-filter-slider-btn-bg: $bg-light-gray; +$search-filter-slider-btn-bg-active: $bg-light-gray-active; +//Serach Pagination +$search-pagination-bg: transparent; +$search-pagination-active-bg: $bg-blue; +$search-pagination-active-color: $text-white; +$search-pagination-hover-color: $text-blue; +$search-pagination-hover-bg: $bg-submenu-active; +$search-pagination-hover-border: $border-basic-active; +//Search selector +$serach-selector-variant-color-active: $text-blue-active; +//Typehead +$tt-color: $text-basic; +$tt-color-active: $text-blue; +$tt-price-color: $text-blue; +$tt-dropdown-bg: $bg-light-gray; +$tt-suggestion-bg-active: $bg-light-gray-active; +$tt-dropdown-border: $border-gray; +//Video +$video-control-bg: $bg-basic-color; +$video-time-color: $text-basic; +$video-time-total-bg: $bg-black; +$video-time-handle-border: $border-gray; +$video-time-handle-bg: $bg-black; +//Form component +$form-bg: transparent; +$form-border: transparent; +$form-color: $text-basic; +//Main +$page-bg: $bg-basic-color; +$page-bg-editor: none; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_fontSizes.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_fontSizes.scss new file mode 100644 index 0000000000000..ca825908578af --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_fontSizes.scss @@ -0,0 +1,16 @@ +$font-small: 11px; +$font-normal: 13px; +$font-medium: 16px; +$font-big: 20px; +$font-extrabig: 24px; +//Navigation +$navigation-font-basic: 18px; +$navigation-font-basic-submenu: 14px; +//Tabs +$tab-font-header: 16px; +//Accordion +$accordion-header: 16px; +//Breadcrumb +$breadcrumb-font: 15px; +// Link List +$link-list-title-font: 15px; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_margins.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_margins.scss new file mode 100644 index 0000000000000..e4e3b68770a14 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/abstracts/vars/_margins.scss @@ -0,0 +1,11 @@ +$default-padding: 5px; +$default-inputs-padding: 12px 10px; + +$extrasmall-margin-bottom: 2px; +$extrasmall-margin: 5px; +$small-margin: 10px; +$middle-margin: 20px; +$large-margin: 30px; +$extralarge-margin: 40px; + +$small-padding: 10px; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/_fonts.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/_fonts.scss new file mode 100644 index 0000000000000..49d54e9f19c92 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/_fonts.scss @@ -0,0 +1 @@ +@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i&subset=cyrillic,cyrillic-ext,greek,greek-ext,latin-ext,vietnamese'); diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/index.scss new file mode 100644 index 0000000000000..2b1a3796bbc5a --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/fonts/index.scss @@ -0,0 +1 @@ +@import 'fonts'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/index.scss new file mode 100644 index 0000000000000..72c7ca6829ec8 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/index.scss @@ -0,0 +1,3 @@ +@import 'fonts'; +@import 'links'; +@import 'reset/ui-datepicker'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/_link-button.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/_link-button.scss new file mode 100644 index 0000000000000..cd6d696c5c09d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/_link-button.scss @@ -0,0 +1,29 @@ +@import '@sass/abstracts/vars/colors'; +@import '@sass/abstracts/mixins'; + +.button-default, +.default { + @include default-link-button(); + background: #f6f6f6; + color: $text-basic; +} +.button-success, +.success { + @include default-link-button(); + background: $btn-green-light; + color: $text-white; + &:hover { + color: $text-white; + background: $btn-green; + } +} +.button-warning, +.warning { + @include default-link-button(); + background: $btn-red; + color: $text-white; + &:hover { + color: $text-white; + background: $btn-red-active; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/index.scss new file mode 100644 index 0000000000000..b47c809b056d3 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/links/index.scss @@ -0,0 +1 @@ +@import 'link-button'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_inputs.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_inputs.scss new file mode 100644 index 0000000000000..2b76bcb99ef67 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_inputs.scss @@ -0,0 +1,67 @@ +@import '@sass/abstracts/mixins'; +@import '@sass/abstracts/vars'; + +label { + background: transparent; + color: $text-basic; +} +input, +button { + display: inline-block; + box-sizing: border-box; + background: $bg-basic-color !important; + border: 1px solid $border-gray; + border-radius: 0 !important; + color: $text-basic; + font-weight: normal; + padding: 8px 2%; + clear: both; + height: auto; + font-size: $font-normal; +} +input:focus { + border: 1px solid $border-gray; +} +input[type='submit'], +input[type='reset'], +input[type='button'], +button { + border: 1px solid $border-basic-color; + padding: 5px 20px; + &:hover { + background: $bg-light-gray !important; + } +} +input::-moz-focus-inner, +button::-moz-focus-inner { + border: 0; + padding: 0; +} +input[type='text'] { + font-size: 13px; +} +input[type='text'], +input[type='email'], +input[type='password'], +textarea, +select { + box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); + color: $text-basic; + width: 100%; + background: #fff; + border: 1px solid $border-gray; +} + +select { + display: inline-block; + vertical-align: middle; + *vertical-align: auto; + *zoom: 1; + *display: inline; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + outline: none; + cursor: pointer; + padding: 5px; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_links.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_links.scss new file mode 100644 index 0000000000000..c83f047bbd14a --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_links.scss @@ -0,0 +1,14 @@ +@import '@sass/abstracts/mixins'; +@import '@sass/abstracts/vars'; + +a { + background-color: transparent; + text-decoration: none; + font-size: 1em; + color: $text-basic; + border-bottom: 1px solid $border-basic-color; + &:hover { + color: $text-basic-active; + text-decoration: none; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_ui-datepicker.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_ui-datepicker.scss new file mode 100644 index 0000000000000..9305794899cf2 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/reset/_ui-datepicker.scss @@ -0,0 +1,7 @@ +@import '@sass/abstracts/vars'; + +.ui-datepicker-title { + select { + color: $text-basic; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext-files-icons.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext-files-icons.scss new file mode 100644 index 0000000000000..59fe03b50cafa --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext-files-icons.scss @@ -0,0 +1,203 @@ +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; +@import '@sass/abstracts/mixins'; + +//files icons +.field-filetypeicon > a > span, +.pdf, +.xls, +.xlsx, +.pptx, +.ppt, +.docx, +.doc, +.bmp, +.png, +.jpg, +.jpeg, +.psd, +.gif, +.avi, +.mp4, +.wmv, +.mov, +.mp3, +.wma, +.txt, +.zip { + display: inline-block; + box-sizing: border-box; + font-weight: normal; + width: 15px; + height: 21px; + margin: 0; + padding: 0; + position: relative; + &:before { + @include fa-icon(); + font-size: 16px !important; + position: absolute; + display: block; + top: 50%; + margin: 0; + padding: 0; + transform: translateY(-50%); + } +} +.field-filetypeicon span:before { + content: $fa-var-file-o; +} +.field-filetypeicon { + .pdf:before { + content: $fa-var-file-pdf-o; + } + .xlsx, + .xls { + &:before { + content: $fa-var-file-excel-o; + } + } + .pptx, + .ppt { + &:before { + content: $fa-var-file-powerpoint-o; + } + } + .docx, + .doc { + &:before { + content: $fa-var-file-word-o; + } + } + .bmp, + .png, + .jpg, + .jpeg, + .psd, + .gif, + .tif { + &:before { + content: $fa-var-file-image-o; + } + } + .avi, + .mp4, + .wmv, + .mov, + .mpg, + .mkv, + .vp6, + .vid, + .rv, + .webm, + .swf, + .flv, + .m4v, + .h264, + .mk3d, + .gifv, + .oggv, + .movie, + .divx { + &:before { + content: $fa-var-file-video-o; + } + } + .mp3, + .wma, + .wav, + .fla, + .flac, + .ra, + .rma, + .aif, + .aiff, + .aa, + .aac, + .mid, + .midi, + .aax, + .ac3, + .au, + .ogg, + .avr, + .m4a, + .mp4a, + .amz, + .mka, + .asx, + .pcm, + .m3u, + .xwma { + &:before { + content: $fa-var-file-audio-o; + } + } + .txt:before { + content: $fa-var-file-text-o; + } + .zip, + .zipx, + .rar, + .tar, + .gz, + .dmg, + .iso { + &:before { + content: $fa-var-file-archive-o; + } + } + .css, + .js, + .py, + .git, + .py, + .cpp, + .h, + .ini, + .config { + &:before { + content: $fa-var-file-code-o; + } + } + .exe, + .jar, + .dll, + .bat, + .pl, + .scr, + .msi, + .app, + .deb, + .apk, + .jar, + .vb, + .prg, + .sh { + &:before { + content: $fa-var-cogs; + } + } + .com, + .net, + .org, + .edu, + .gov, + .mil, + .html, + .htm, + .xhtml, + .jhtml, + .php, + .php3, + .php4, + .php5, + .phtmle, + .asp, + .aspx, + .cfm { + &:before { + content: $fa-var-link; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext.scss new file mode 100644 index 0000000000000..7d5ec313860d8 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/_richtext.scss @@ -0,0 +1,101 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + color: $text-heading-color; +} +h1, +h2 { + margin: $small-margin 0; +} +h3, +h4, +p { + margin: $extrasmall-margin 0; +} +h5, +h6 { + margin: $extrasmall-margin 0 0; +} +strong { + font-weight: 700; +} +ul, +ol { + padding-bottom: $extrasmall-margin; + padding-top: $extrasmall-margin; + margin-left: $small-margin; +} +li { + font-size: $font-normal; + margin-left: 15px; +} +ul { + li { + list-style: disc; + list-style-position: inside; + } +} +ol { + li { + list-style: decimal; + list-style-position: inside; + } +} +a { + color: $rich-content-link-color; + text-decoration: underline; + font-size: 1em; + &:hover { + color: $rich-content-link-color-active; + } +} +table { + height: auto !important; + border: 2px solid $border-gray; + &, + tr, + th, + td { + border: solid 2px $border-gray; + background: $bg-basic-color; + border-collapse: collapse; + vertical-align: middle; + } + tr, + th, + td { + padding: 5px; + } + caption { + background-color: $bg-light-gray; + overflow: hidden; + padding: 10px; + font-size: $font-big; + font-weight: bold; + margin-left: 0; + } + tr { + border: none; + } + th, + td { + border-width: 2px 0 0 2px; + } + th { + background-color: lighten($bg-light-gray, 5%); + font-size: $font-normal; + font-weight: bold; + padding: 7px; + &:first-child { + border-left: 0; + } + } + td { + &:first-child { + border-left: 0; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/index.scss new file mode 100644 index 0000000000000..1ba07dc731cd9 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/richtext/index.scss @@ -0,0 +1,2 @@ +@import 'richtext'; +@import 'richtext-files-icons'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss new file mode 100644 index 0000000000000..0365acda25c0c --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss @@ -0,0 +1,95 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.twitter-typeahead { + display: inline-block; + vertical-align: middle; + max-width: 100%; + width: 100%; +} +.tt-menu { + background: $bg-basic-color; + width: 100%; + border: 1px solid $border-gray; +} +.tt-hint { + color: $tt-color; +} +.tt-dropdown-menu { + width: 250px; + margin-top: 5px; + background-color: $tt-dropdown-bg; + border: 1px solid $tt-dropdown-border; + max-height: 300px; + overflow-y: auto; + box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.08); +} +.tt-suggestion { + padding: 4px 10px; + color: $tt-color; + overflow: hidden; + a { + text-decoration: none; + } + &:last-child { + border: none; + } + .field-image { + width: 100px; + float: left; + margin-right: 10px; + } + .field-make { + font-size: 15px; + float: left; + margin-right: 5px; + } + .field-model { + margin-left: 4px; + font-size: 15px; + font-weight: bold; + width: 100%; + } + .field-priceformatted { + float: right; + font-size: 15px; + color: $tt-price-color; + margin-top: -20px; + } +} +.tt-suggestion.tt-cursor { + color: $tt-color-active; + background-color: $tt-suggestion-bg-active; + cursor: pointer; +} +.loading-in-progress { + .tt-dropdown-menu { + display: block !important; + min-height: 50px; + position: relative; + &:after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + margin-top: -20px; + margin-left: -20px; + height: 40px; + width: 50px; + display: block; + @include loading-gif(); + z-index: 11; + } + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: $tt-dropdown-bg; + opacity: 0.8; + z-index: 10; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/index.scss new file mode 100644 index 0000000000000..c0b2466dbfa04 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/index.scss @@ -0,0 +1 @@ +@import 'typehead'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-column-splitter.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-column-splitter.scss new file mode 100644 index 0000000000000..0aea965b660ac --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-column-splitter.scss @@ -0,0 +1,14 @@ +@import '@sass/abstracts/vars'; + +.row.column-splitter { + margin-left: 0; + margin-right: 0; + padding-left: $default-padding / 2; + padding-right: $default-padding / 2; + max-width: none; + + > div { + padding-left: $default-padding; + padding-right: $default-padding; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-container.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-container.scss new file mode 100644 index 0000000000000..86bee01402d61 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-container.scss @@ -0,0 +1,21 @@ +@import '@sass/abstracts/mixins'; + +.container-wrapper { + width: 100%; +} + +.component { + position: relative; +} + +.container { + padding: 0; + + &.fullwidth-container { + max-width: unset; + } + + .component-content { + @include clearfix(); + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-image.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-image.scss new file mode 100644 index 0000000000000..92efb3b9ad0ad --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-image.scss @@ -0,0 +1,18 @@ +@import '@sass/abstracts/vars'; + +.image { + img { + max-width: 100%; + height: auto; + } + a { + display: inline-block; + max-width: 100%; + } + .image-caption { + display: block; + font-style: italic; + font-size: $font-small; + color: $image-caption-color; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-navigation.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-navigation.scss new file mode 100644 index 0000000000000..9af44e6e91650 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-navigation.scss @@ -0,0 +1,54 @@ +@import '@sass/abstracts/mixins'; +@import '@sass/abstracts/vars'; + +.navigation { + background: $nav-bg; + ul { + padding-left: 0; + } + .level0, + .level1 { + > .navigation-title > a { + font-size: $navigation-font-basic; + border-color: $nav-border-root; + border-style: solid; + border-width: 0 0 2px 0; + padding-right: 10px; + margin-right: 5px; + &:hover { + text-decoration: none; + } + } + } + a { + color: $nav-color-root; + .lt-ie9 &, + .lt-ie9 & span { + color: $nav-color-root; + } + &:focus, + &:hover { + color: $nav-color-root-active; + } + } + li { + &.submenu { + margin-bottom: 0; + } + > .navigation-title { + > a { + padding: 3px 5px 3px 0; + display: block; + color: $nav-color-root; + text-decoration: none; + } + } + > ul a { + font-size: $navigation-font-basic-submenu; + } + } + .submenu > ul { + padding-left: 10px; + } +} +@import '@sass/components/navigation/'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-promo.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-promo.scss new file mode 100644 index 0000000000000..77064f569b950 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-promo.scss @@ -0,0 +1,42 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.promo { + background: $promo-bg; + padding: 15px; + overflow: hidden; + box-sizing: border-box; + > .component-content { + position: relative; + @include clearfix(); + @include border-basic(all, $promo-border); + + > div { + padding: 5px; + } + } + .zg-height-fix { + .field-promoicon { + margin-top: 100px; + } + } + .field-promoicon { + overflow: hidden; + width: 100%; + img { + width: 100%; + height: auto; + } + } + .field-promolink { + margin-top: 5px; + padding-bottom: 10px; + } + &.image-full-size { + img { + margin-bottom: 10px; + } + } + @import '@sass/variants/promo'; + @import '@sass/base/richtext/richtext'; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-richtext-content.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-richtext-content.scss new file mode 100644 index 0000000000000..6cd5e8c531fcb --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/_component-richtext-content.scss @@ -0,0 +1,20 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.content, +.rich-text { + border: $rich-content-border; + line-height: 1.5; + font-size: 12px; + overflow: hidden; + * { + max-width: 100%; + } + @import '@sass/base/richtext'; +} +.rich-text { + @import '@sass/variants/rich-text'; +} +.content { + @import '@sass/variants/page-content'; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_alignment.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_alignment.scss new file mode 100644 index 0000000000000..bea37718d81c6 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_alignment.scss @@ -0,0 +1,26 @@ +.position-left, +.position-left * { + text-align: left !important; +} + +.position-right, +.position-right * { + text-align: right !important; +} + +.position-center, +.position-center * { + text-align: center !important; +} + +.position-left select { + direction: ltr !important; +} + +.position-right select { + direction: rtl !important; +} + +.position-center select { + text-align-last: center !important; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_boxed.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_boxed.scss new file mode 100644 index 0000000000000..2345bcade3749 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_boxed.scss @@ -0,0 +1,16 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.boxed { + box-sizing: border-box; + margin: 20px 0; + @include respond-to(tablet) { + padding: 10px; + } + @include respond-to(mobile) { + padding: 10px; + } + > div { + @include wrapper(); + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_clearfix.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_clearfix.scss new file mode 100644 index 0000000000000..0f85b51c78219 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_clearfix.scss @@ -0,0 +1,11 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.component-content-clearfix { + .component-content { + @include clearfix; + } +} +.component-clearfix { + @include clearfix; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_highlighted.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_highlighted.scss new file mode 100644 index 0000000000000..d0d37d0bb3661 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_highlighted.scss @@ -0,0 +1,63 @@ +.highlighted-top { + background: #ffffff; + border-top-width: 3px; + border-top-color: #15909c; + border-style: solid; + padding: 25px; + margin: 0; +} + +.highlighted-top h1, +.highlighted-top h2, +.highlighted-top h3, +.highlighted-top h4 { + margin: 0 0 10px 0; +} + +.highlighted-bottom { + background: #ffffff; + border-bottom-width: 3px; + border-bottom-color: #15909c; + border-style: solid; + padding: 25px; + margin: 0; +} + +.highlighted-bottom h1, +.highlighted-bottom h2, +.highlighted-bottom h3, +.highlighted-bottom h4 { + margin: 0 0 10px 0; +} + +.highlighted-left { + background: #ffffff; + border-left-width: 3px; + border-left-color: #15909c; + border-style: solid; + padding: 25px; + margin: 0; +} + +.highlighted-left h1, +.highlighted-left h2, +.highlighted-left h3, +.highlighted-left h4 { + margin: 0 0 10px 0; +} + +.highlighted-right { + background: #ffffff; + border-right-width: 3px; + border-right-color: #15909c; + border-style: solid; + padding: 25px; + margin: 0; +} + +.highlighted-right h1, +.highlighted-right h2, +.highlighted-right h3, +.highlighted-right h4 { + margin: 0 0 10px 0; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_link-button.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_link-button.scss new file mode 100644 index 0000000000000..ec7cec5df6f9c --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_link-button.scss @@ -0,0 +1,18 @@ +@import '@sass/abstracts/mixins'; + +.link-button { + @import '@sass/base/links/'; +} +// Promo button +.promo.link-button { + a { + @extend .button-default; + } +} +.link.link-button { + .is-empty-hint, + .field-link span, + a { + @include default-link-button(); + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_promoted-box.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_promoted-box.scss new file mode 100644 index 0000000000000..7b4ec35ba932d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/_promoted-box.scss @@ -0,0 +1,3 @@ +.promoted-box { + border: none !important; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/index.scss new file mode 100644 index 0000000000000..d3a66a141629e --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/common/index.scss @@ -0,0 +1,6 @@ +@import 'alignment'; +@import 'boxed'; +@import 'clearfix'; +@import 'highlighted'; +@import 'link-button'; +@import 'promoted-box'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_bordered.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_bordered.scss new file mode 100644 index 0000000000000..4510a073599e0 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_bordered.scss @@ -0,0 +1,24 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.sxa-bordered { + box-sizing: border-box; + > .component-content { + padding: 0; + @include border-basic(); + border-radius: 5px; + } +} + +.column-splitter, +.row-splitter { + box-sizing: border-box; + .sxa-bordered { + padding: $default-padding !important; + > .component, + .scEmptyPlaceholder { + @include border-basic(); + border-radius: 5px; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_title-row-box.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_title-row-box.scss new file mode 100644 index 0000000000000..76b13e2e0b0f4 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/_title-row-box.scss @@ -0,0 +1,69 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.title-row-box { + @include border-basic(); + box-sizing: border-box; + width: 100%; + height: 87px; + margin: 0; + padding: 0; + background: $container-title-row-bg; + > .component-content { + @include wrapper(); + .title { + display: inline-block; + vertical-align: middle; + box-sizing: border-box; + margin: 23px 0 0 0; + padding: 0; + h1 { + @include font-size(2.2); + border: none; + } + @include respond-to(all-mobile) { + margin: 23px 0 0 20px; + } + } + .rich-text { + margin: 0; + h1, + h2, + h3, + h4 { + margin: 0; + padding: 0; + } + } + .breadcrumb { + display: inline-block; + vertical-align: middle; + box-sizing: border-box; + @include font-size(1.4); + margin: 23px 0 0 0; + padding: 0; + float: right; + clear: both; + @include respond-to(tablet) { + margin: 23px 20px 0 0; + } + @include respond-to(mobile) { + display: none; + } + } + } + @include respond-to(all-mobile) { + .alpha { + vertical-align: middle; + box-sizing: border-box; + width: auto !important; //overrides grid + float: left; + } + .omega { + vertical-align: middle; + box-sizing: border-box; + width: auto !important; //overrides grid + float: right; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/index.scss new file mode 100644 index 0000000000000..8b09323a3e329 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/container/index.scss @@ -0,0 +1 @@ +@import 'bordered'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-left.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-left.scss new file mode 100644 index 0000000000000..5be626a2a5891 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-left.scss @@ -0,0 +1,3 @@ +.image-left .component-content > div > img { + float: left; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-right.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-right.scss new file mode 100644 index 0000000000000..07fd291c664b9 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image-alignment/_image-right.scss @@ -0,0 +1,3 @@ +.image-right .component-content > div > img { + float: right; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-banner.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-banner.scss new file mode 100644 index 0000000000000..fb8b877ea90e5 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-banner.scss @@ -0,0 +1,15 @@ +.hero-banner { + .component-content { + background-position: center; + background-repeat: no-repeat; + background-size: cover; + height: 800px; + + @include respond-to(mobile-large) { + height: 300px; + } + } + .sc-image-wrapper { + opacity: 0; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-default-size.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-default-size.scss new file mode 100644 index 0000000000000..7e1771ff5c1d4 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/_image-default-size.scss @@ -0,0 +1,6 @@ +.image-default-size { + img { + max-width: none; + width: auto !important; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/index.scss new file mode 100644 index 0000000000000..5a79b6155e8bb --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/image/index.scss @@ -0,0 +1,2 @@ +@import 'image-default-size'; +@import 'image-banner'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/index.scss new file mode 100644 index 0000000000000..d93583e8a490e --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/index.scss @@ -0,0 +1,17 @@ +@import 'component-column-splitter'; +@import 'component-container'; +@import 'component-image'; +@import 'component-navigation'; +@import 'component-promo'; +@import '_component-richtext-content'; + +@import 'common'; +@import 'container'; +@import 'layout'; +@import 'spacing'; +@import 'promo'; +@import 'spacing'; +@import 'title'; +@import 'image'; +@import 'link-list'; +@import 'rich-text'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_acaindent.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_acaindent.scss new file mode 100644 index 0000000000000..b435f32d93d81 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_acaindent.scss @@ -0,0 +1,5 @@ +@import '@sass/abstracts/vars'; + +.alan-indent { + margin: 0 $extralarge-margin; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_background.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_background.scss new file mode 100644 index 0000000000000..b11ee2982906c --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/_background.scss @@ -0,0 +1,27 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +%cover-bg { + background-repeat: no-repeat; + background-size: cover; +} +.cover-background { + > .component-content { + @extend %cover-bg; + } +} +.fix-background { + > .component-content { + @extend %cover-bg; + @include fixed-bg(left top); + } +} +.parallax-background { + > .component-content { + @extend %cover-bg; + @include fixed-bg(50% 0); + @include respond-to(mobile-large) { + background-attachment: scroll; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/index.scss new file mode 100644 index 0000000000000..38924a7477198 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/layout/index.scss @@ -0,0 +1 @@ +@import 'background'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_component-link-list.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_component-link-list.scss new file mode 100644 index 0000000000000..9441f03c26c73 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_component-link-list.scss @@ -0,0 +1,50 @@ +@import '@sass/abstracts/mixins'; +@import '@sass/abstracts/vars'; +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; + +.link-list { + background: $link-list-bg; + h1, + h2, + h3, + h4, + h5, + h6 { + @include border-basic(bottom, $link-list-header-border); + } + > .component-content { + ul { + background: $link-list-items-bg; + } + li { + background: $link-list-item-bg; + display: block; + font-size: $font-normal; + a { + display: inline; + color: $link-list-item-color; + position: relative; + padding-left: 10px; + font-size: 1em; + text-decoration: none; + &:before { + @include fa-icon(); + content: $fa-var-chevron-right; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); + font-size: 10px; + } + &:hover { + color: $link-list-item-color-active; + text-decoration: none; + border-bottom: 1px solid $link-list-item-border-active; + } + } + } + } + @import '../../base/links'; + @import '../../variants/link-list'; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_list-vertical.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_list-vertical.scss new file mode 100644 index 0000000000000..50f71e6ff90a4 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/_list-vertical.scss @@ -0,0 +1,19 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.link-list.list-vertical { + h3 { + background: $bg-basic-color; + width: 100%; + display: inline-block; + padding: 3px 5px; + @include border-basic(); + } + a { + border: none; + } + li { + display: block; + margin-left: $middle-margin; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/index.scss new file mode 100644 index 0000000000000..cf000d7cda705 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/link-list/index.scss @@ -0,0 +1,2 @@ +@import 'component-link-list'; +@import 'list-vertical'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-fat.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-fat.scss new file mode 100644 index 0000000000000..06453f04f38e1 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-fat.scss @@ -0,0 +1,57 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; + +.navigation.navigation-fat { + background: $bg-basic-color; + @include border-basic(); + + a { + text-decoration: none; + } + + nav > ul { + list-style: none; + padding: 10px 0; + overflow: hidden; + } + + .rel-level1 { + margin: $small-margin; + padding: 0; + display: inline-block; + vertical-align: top; + + &.submenu ul a { + position: relative; + &:before { + @include fa-icon(); + transform: translateY(-50%); + position: absolute; + content: $fa-var-chevron-right; + top: 50%; + left: -9px; + font-size: 10px; + } + } + > .navigation-title > a { + @include border-basic(top, $border-basic-color, 2px); + border-bottom: 0; + background: $nav-bg-root; + padding: 5px 10px; + display: block; + width: auto; + &:hover { + border-color: $menu-hover-color; + } + } + > ul { + padding: 0; + } + } + .rel-level2 { + padding-left: $small-margin; + display: block; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-main-horizontal-vertical.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-main-horizontal-vertical.scss new file mode 100644 index 0000000000000..973ea5007f3f2 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-main-horizontal-vertical.scss @@ -0,0 +1,158 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; + +$borderSize: 2px; + +//Drop Down Navigation Common Part +.navigation.navigation-main { + .component-content > nav { + position: relative; + ul { + @include clearfix(); + } + } + .rel-level1 { + float: left; + &.active { + > .navigation-title > a { + border-color: $nav-border-root; + } + } + > .navigation-title > a { + border-width: 2px 0 0 0; + border-color: transparent; + &:hover { + border-color: $nav-border-root; + } + } + &.submenu { + > .navigation-title a { + position: relative; + padding-right: 15px; + &:after { + @include fa-icon(); + font-size: 10px; + content: $fa-var-chevron-down; + position: absolute; + transform: translateY(-50%); + top: 50%; + right: 0; + } + } + } + //submenu + > ul { + overflow: hidden; + display: none; + z-index: 10; + position: absolute; + top: 100%; + background: $nav-bg-submenu; + margin-left: 0; + margin-top: -$borderSize; + border-top: $borderSize solid $nav-border-submenu; + border-left: 1px solid $nav-submenu-item-border; + border-bottom: 1px solid $nav-submenu-item-border; + } + &:active, + &:hover { + > a { + & + ul { + display: block !important; + } + } + > ul { + display: block !important; + min-width: 60px; + } + } + &.active { + > .navigation-title > a:link, + > .navigation-title > a:visited { + color: $text-basic-active; + } + > span { + display: block; + padding: 10px 20px; + color: $text-white; + } + } + &.submenu.active { + border-color: $menu-active-color; + } + } + .rel-level2 { + &:hover, + &:focus { + transition: background 0.2s ease-in; + background: $nav-bg-submenu-active; + } + div > a { + display: block; + font-weight: normal; + font-size: $navigation-font-basic-submenu; + text-align: center; + &:hover, + &:focus { + color: $nav-color-submenu; + } + } + &.submenu { + box-sizing: border-box; + &.navigation-image { + text-align: center; + > a, + .field-navigationtext { + text-align: left; + } + } + } + } + // Additional styles fot drop down horizontal navigation + &.navigation-main-horizontal { + .submenu > ul { + padding-left: 0; + } + .rel-level1 { + &:active, + &:hover { + > a { + & + ul { + display: inline-flex !important; + flex-wrap: wrap; + } + } + > ul { + display: inline-flex !important; + flex-wrap: wrap; + } + } + > ul { + width: 100%; + clear: both; + left: 0; + } + } + .rel-level2 { + float: left; + padding: 10px; + @include border-basic(right, $nav-submenu-item-border, 1px); + flex-grow: 1; + flex-basis: 23%; + } + } + // Additional styles fot drop down vertical navigation + &.navigation-main-vertical { + .rel-level1 > ul { + padding-left: 0; + width: auto; + left: auto; + @include border-basic(right, $nav-submenu-item-border, 1px); + > li { + padding: 5px 10px; + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-mobile.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-mobile.scss new file mode 100644 index 0000000000000..33b534c557c52 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-mobile.scss @@ -0,0 +1,89 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; + +.navigation.navigation-mobile { + nav > ul { + border: none; + @include border-basic(); + } + .rel-level1 { + cursor: pointer; + margin: 0; + background: $bg-basic-color; + > ul { + li { + position: relative; + a:before { + @include fa-icon(); + content: $fa-var-chevron-right; + display: block; + position: absolute; + left: 0; + font-size: 10px; + top: 20px; + transform: translateY(-50%); + } + } + padding-left: 25px; + display: none; + background: $nav-bg-submenu; + } + &.submenu { + > ul { + display: none; + } + &:focus { + > .navigation-title:before { + transform: rotate(180deg); + transition: 0.6s; + transform-style: preserve-3d; + } + > ul { + display: block; + } + } + > .navigation-title { + position: relative; + &:before { + @include fa-icon(); + content: $fa-var-chevron-down; + display: block; + position: absolute; + right: 10px; + font-size: 10px; + top: 20px; + transform: translateY(-50%); + transform: rotate(0); + transition: 0.6s; + transform-style: preserve-3d; + } + } + } + > .navigation-title { + border-bottom: 1px solid $border-basic-color; + margin: 0; + &:last-child { + border-bottom: none; + } + } + .navigation-title { + padding: 10px; + > a { + text-decoration: none; + color: $text-basic; + display: inline; + } + } + } + .rel-level2 { + display: list-item; + .navigation-title > a { + font-weight: 500; + } + ul { + display: none; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-sidebar.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-sidebar.scss new file mode 100644 index 0000000000000..0371680494f51 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_navigation-sidebar.scss @@ -0,0 +1,29 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.navigation.navigation-sidebar { + a { + text-decoration: none; + } + nav > ul { + .rel-level1 { + > .navigation-title { + margin-bottom: 0; + > a { + padding: 5px 10px; + display: block; + position: relative; + z-index: 1; + margin-right: 0; + } + } + > ul { + margin-left: $small-margin; + margin-top: $extrasmall-margin; + } + } + .rel-level2 { + display: block; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_sitemap-navigation.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_sitemap-navigation.scss new file mode 100644 index 0000000000000..95725b916497a --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/_sitemap-navigation.scss @@ -0,0 +1,20 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; +@import '@fontawesome/scss/mixins'; +@import '@fontawesome/scss/variables'; + +.navigation.sitemap-navigation { + .level2 a { + position: relative; + padding-left: 10px; + &:before { + @include font-size(1.4); + @include fa-icon(); + transform: translateY(-50%) scale(1, -1); + position: absolute; + content: $fa-var-share; + top: 50%; + left: -8px; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/index.scss new file mode 100644 index 0000000000000..6850050e43c81 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/navigation/index.scss @@ -0,0 +1,5 @@ +@import 'navigation-main-horizontal-vertical'; +@import 'navigation-mobile'; +@import 'navigation-sidebar'; +@import 'sitemap-navigation'; +@import 'navigation-fat'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_absolute-bottom-link.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_absolute-bottom-link.scss new file mode 100644 index 0000000000000..f6589e1802bb8 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_absolute-bottom-link.scss @@ -0,0 +1,8 @@ +.promo.absolute-bottom-link { + position: relative; + .field-promolink { + position: absolute; + bottom: 10px; + right: 10px; + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-hero.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-hero.scss new file mode 100644 index 0000000000000..9845d64701422 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-hero.scss @@ -0,0 +1,42 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.promo.promo-hero { + position: relative; + text-align: center; + &.promo-hero-half { + float: left; + width: 50%; + @include respond-to(all-mobile) { + float: none; + width: 100%; + } + } + .field-promotext { + display: inline-block; + transform: translateY(-50%); + position: absolute; + top: 50%; + left: 0; + right: 0; + padding: 20px; + color: $promo-hero-text-color; + background: $promo-bg-hero; + > a { + color: inherit; + text-decoration: none; + } + @include respond-to(all-mobile) { + width: 100%; + margin: 0; + h1 { + @include font-size(2.4); + } + h2, + h3, + h4 { + @include font-size(2); + } + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-shadow.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-shadow.scss new file mode 100644 index 0000000000000..be34b9fc1a5b1 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/_promo-shadow.scss @@ -0,0 +1,43 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.promo-shadow { + max-width: 960px; + padding: 0; + border-top-width: 3px; + border-top-color: $promo-shadow-border; + border-style: solid; + overflow: visible; + position: relative; + &.promo { + float: left; + } + > .component-content { + @include respond-to(all-mobile) { + margin: 0 10px 30px 10px; + } + padding: 15px; + margin: 0 0 30px 0; + &:before, + &:after { + opacity: 0.7; + box-shadow: 0 17px 10px rgba(0, 0, 0, 0.7); + position: absolute; + z-index: -1; + height: 20%; + max-height: 100px; + max-width: 460px; + width: 47%; + content: ''; + bottom: 10px; + } + &:before { + left: 2%; + transform: rotate(-3deg); + } + &:after { + right: 2%; + transform: rotate(3deg); + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/index.scss new file mode 100644 index 0000000000000..1c71782f60971 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/promo/index.scss @@ -0,0 +1,3 @@ +@import 'absolute-bottom-link'; +@import 'promo-hero'; +@import 'promo-shadow'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/_rich-text-lists.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/_rich-text-lists.scss new file mode 100644 index 0000000000000..9d7b3bc88ba16 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/_rich-text-lists.scss @@ -0,0 +1,63 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.rich-text-lists, +.field-featurelist { + ul { + box-sizing: border-box; + margin: 0; + padding: 0; + li { + @include font-size(1.3); + position: relative; + line-height: 21px; + list-style: none; + margin: 0; + padding: 5px 0 5px 25px; + &:before { + display: inline-block; + vertical-align: middle; + @include font-size(1.2); + font-family: 'FontAwesome', sans-serif; + position: absolute; + top: 3px; + left: 0; + color: $text-basic; + text-align: center; + content: '\f00c'; + width: 20px; + margin: 0 5px 0 0; + padding: 0; + } + } + } +} +.field-featurelist { + ul { + li { + &:before { + display: inline-block; + vertical-align: middle; + @include font-size(1.2); + font-family: 'FontAwesome', sans-serif; + position: absolute; + top: 3px; + left: 0; + color: $text-basic; + text-align: center; + content: '\f046'; + width: 20px; + margin: 0 5px 0 0; + padding: 0; + } + } + } +} +.media-link { + &.file-type-icon-media-link { + float: left; + .field-filetypeicon { + text-align: center; + } + } +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/index.scss new file mode 100644 index 0000000000000..6e89c6a0e1853 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/rich-text/index.scss @@ -0,0 +1 @@ +@import 'rich-text-lists'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_background-colors.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_background-colors.scss new file mode 100644 index 0000000000000..30afeef82ee4d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_background-colors.scss @@ -0,0 +1,14 @@ +@import '@sass/abstracts/vars'; + +.container-gray-background { + background: $bg-light-gray; +} +.container-clean-background { + background: $bg-basic-color; +} +.container-dark-background { + background: $bg-black-active; +} +.container-color-background { + background: $bg-blue; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_indent.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_indent.scss new file mode 100644 index 0000000000000..9d2f599e66b08 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/_indent.scss @@ -0,0 +1,10 @@ +@import '@sass/abstracts/vars'; +.indent { + margin: 0 $extralarge-margin; +} +.indent-top { + margin-top: $middle-margin; +} +.indent-bottom { + margin-bottom: $middle-margin; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/index.scss new file mode 100644 index 0000000000000..6d31d378d6dd9 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/spacing/index.scss @@ -0,0 +1,2 @@ +@import 'background-colors'; +@import 'indent'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/_component-title.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/_component-title.scss new file mode 100644 index 0000000000000..4fe0e836f3d6d --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/_component-title.scss @@ -0,0 +1,25 @@ +@import '@sass/abstracts/vars'; +@import '@sass/abstracts/mixins'; + +.title { + background: $title-bg; + h1, + .field-title { + > a, + > span { + @include border-basic(bottom, $border-basic-color); + font-size: $font-extrabig; + margin-bottom: $small-margin; + color: $title-color; + line-height: normal; + padding-bottom: 10px; + display: block; + text-decoration: none; + cursor: pointer; + &:hover { + color: $title-color-active; + } + } + } + @import '@sass/variants/title'; +} diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/index.scss new file mode 100644 index 0000000000000..f91198792de84 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/components/title/index.scss @@ -0,0 +1 @@ +@import 'component-title'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/main.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/main.scss new file mode 100644 index 0000000000000..87f251596147b --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/main.scss @@ -0,0 +1,4 @@ +@import 'base'; +@import 'components'; +@import 'variants'; +@import 'app'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/index.scss new file mode 100644 index 0000000000000..5064fee7c2568 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/index.scss @@ -0,0 +1,6 @@ +@import 'link-list'; +@import 'navigation'; +@import 'page-content'; +@import 'promo'; +@import 'rich-text'; +@import 'title'; diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/link-list/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/link-list/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/navigation/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/navigation/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/page-content/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/page-content/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/promo/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/promo/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/rich-text/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/rich-text/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/variants/title/index.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/variants/title/index.scss new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/examples/cms-sitecore-xmcloud/src/components/ColumnSplitter.tsx b/examples/cms-sitecore-xmcloud/src/components/ColumnSplitter.tsx new file mode 100644 index 0000000000000..995778c92f1d5 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/ColumnSplitter.tsx @@ -0,0 +1,65 @@ +import React from 'react' +import { + ComponentParams, + ComponentRendering, + Placeholder, +} from '@sitecore-jss/sitecore-jss-nextjs' + +interface ComponentProps { + rendering: ComponentRendering & { params: ComponentParams } + params: ComponentParams +} + +export const Default = (props: ComponentProps): JSX.Element => { + const styles = `${props.params.GridParameters ?? ''} ${ + props.params.Styles ?? '' + }`.trimEnd() + const columnWidths = [ + props.params.ColumnWidth1, + props.params.ColumnWidth2, + props.params.ColumnWidth3, + props.params.ColumnWidth4, + props.params.ColumnWidth5, + props.params.ColumnWidth6, + props.params.ColumnWidth7, + props.params.ColumnWidth8, + ] + const columnStyles = [ + props.params.Styles1, + props.params.Styles2, + props.params.Styles3, + props.params.Styles4, + props.params.Styles5, + props.params.Styles6, + props.params.Styles7, + props.params.Styles8, + ] + const enabledPlaceholders = props.params.EnabledPlaceholders.split(',') + const id = props.params.RenderingIdentifier + + return ( +
+ {enabledPlaceholders.map((ph, index) => { + const phKey = `column-${ph}-{*}` + const phStyles = `${columnWidths[+ph - 1]} ${ + columnStyles[+ph - 1] ?? '' + }`.trimEnd() + + return ( +
+
+ +
+
+ ) + })} +
+ ) +} diff --git a/examples/cms-sitecore-xmcloud/src/components/Container.tsx b/examples/cms-sitecore-xmcloud/src/components/Container.tsx new file mode 100644 index 0000000000000..b880da06a9d06 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/Container.tsx @@ -0,0 +1,67 @@ +import React from 'react' +import { + ComponentParams, + ComponentRendering, + Placeholder, + useSitecoreContext, +} from '@sitecore-jss/sitecore-jss-nextjs' + +const BACKGROUND_REG_EXP = new RegExp( + /[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/gi +) + +interface ComponentProps { + rendering: ComponentRendering & { params: ComponentParams } + params: ComponentParams +} + +const DefaultContainer = (props: ComponentProps): JSX.Element => { + const { sitecoreContext } = useSitecoreContext() + const containerStyles = + props.params && props.params.Styles ? props.params.Styles : '' + const styles = `${props.params.GridParameters} ${containerStyles}`.trimEnd() + const phKey = `container-${props.params.DynamicPlaceholderId}` + const id = props.params.RenderingIdentifier + let backgroundImage = props.params.BackgroundImage as string + let backgroundStyle: { [key: string]: string } = {} + + if (backgroundImage) { + const prefix = `${ + sitecoreContext.pageState !== 'normal' ? '/sitecore/shell' : '' + }/-/media/` + backgroundImage = `${backgroundImage + ?.match(BACKGROUND_REG_EXP) + ?.pop() + ?.replace(/-/gi, '')}` + backgroundStyle = { + backgroundImage: `url('${prefix}${backgroundImage}')`, + } + } + + return ( +
+
+
+ +
+
+
+ ) +} + +export const Default = (props: ComponentProps): JSX.Element => { + const splitStyles = props.params?.Styles?.split(' ') + + if (splitStyles && splitStyles.includes('container')) { + return ( +
+ +
+ ) + } + + return +} diff --git a/examples/cms-sitecore-xmcloud/src/components/ContentBlock.tsx b/examples/cms-sitecore-xmcloud/src/components/ContentBlock.tsx new file mode 100644 index 0000000000000..33540cb07ea89 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/ContentBlock.tsx @@ -0,0 +1,29 @@ +import { + Text, + RichText, + Field, + withDatasourceCheck, +} from '@sitecore-jss/sitecore-jss-nextjs' +import { ComponentProps } from 'lib/component-props' + +type ContentBlockProps = ComponentProps & { + fields: { + heading: Field + content: Field + } +} + +/** + * A simple Content Block component, with a heading and rich text block. + * This is the most basic building block of a content site, and the most basic + * JSS component that's useful. + */ +const ContentBlock = ({ fields }: ContentBlockProps): JSX.Element => ( +
+ + + +
+) + +export default withDatasourceCheck()(ContentBlock) diff --git a/examples/cms-sitecore-xmcloud/src/components/FEaaSWrapper.tsx b/examples/cms-sitecore-xmcloud/src/components/FEaaSWrapper.tsx new file mode 100644 index 0000000000000..00bc5756f1e6e --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/FEaaSWrapper.tsx @@ -0,0 +1,18 @@ +import { + FEaaSComponent, + FEaaSComponentProps, +} from '@sitecore-jss/sitecore-jss-nextjs' +import React from 'react' + +export const Default = (props: FEaaSComponentProps): JSX.Element => { + const styles = `component feaas ${props.params?.styles}`.trimEnd() + const id = props.params?.RenderingIdentifier + + return ( +
+
+ +
+
+ ) +} diff --git a/examples/cms-sitecore-xmcloud/src/components/Image.tsx b/examples/cms-sitecore-xmcloud/src/components/Image.tsx new file mode 100644 index 0000000000000..07032ebd373a6 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/Image.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import { + Image as JssImage, + Link as JssLink, + ImageField, + Field, + LinkField, + Text, + useSitecoreContext, +} from '@sitecore-jss/sitecore-jss-nextjs' + +interface Fields { + Image: ImageField + ImageCaption: Field + TargetUrl: LinkField +} + +type ImageProps = { + params: { [key: string]: string } + fields: Fields +} + +const ImageDefault = (props: ImageProps): JSX.Element => ( +
+
+ Image +
+
+) + +export const Banner = (props: ImageProps): JSX.Element => { + const { sitecoreContext } = useSitecoreContext() + const backgroundStyle = { + backgroundImage: `url('${props?.fields?.Image?.value?.src}')`, + } + const modifyImageProps = { + ...props.fields.Image, + editable: props?.fields?.Image?.editable + ?.replace(`width="${props?.fields?.Image?.value?.width}"`, 'width="100%"') + .replace( + `height="${props?.fields?.Image?.value?.height}"`, + 'height="100%"' + ), + } + const id = props.params.RenderingIdentifier + + return ( +
+
+ {sitecoreContext.pageEditing ? ( + + ) : ( + '' + )} +
+
+ ) +} + +export const Default = (props: ImageProps): JSX.Element => { + const { sitecoreContext } = useSitecoreContext() + + if (props.fields) { + const Image = () => + const id = props.params.RenderingIdentifier + + return ( +
+
+ {sitecoreContext.pageState === 'edit' ? ( + + ) : ( + + + + )} + +
+
+ ) + } + + return +} diff --git a/examples/cms-sitecore-xmcloud/src/components/LinkList.tsx b/examples/cms-sitecore-xmcloud/src/components/LinkList.tsx new file mode 100644 index 0000000000000..a71d5909ff919 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/LinkList.tsx @@ -0,0 +1,92 @@ +import React from 'react' +import { + Link as JssLink, + Text, + LinkField, + TextField, +} from '@sitecore-jss/sitecore-jss-nextjs' + +type ResultsFieldLink = { + field: { + link: LinkField + } +} + +interface Fields { + data: { + datasource: { + children: { + results: ResultsFieldLink[] + } + field: { + title: TextField + } + } + } +} + +type LinkListProps = { + params: { [key: string]: string } + fields: Fields +} + +type LinkListItemProps = { + key: string + index: number + total: number + field: LinkField +} + +const LinkListItem = (props: LinkListItemProps) => { + let className = `item${props.index}` + className += (props.index + 1) % 2 == 0 ? ' even' : ' odd' + if (props.index == 0) { + className += ' first' + } + if (props.index + 1 == props.total) { + className += ' last' + } + return ( +
  • +
    + +
    +
  • + ) +} + +export const Default = (props: LinkListProps): JSX.Element => { + const datasource = props.fields?.data?.datasource + const styles = `component link-list ${props.params.styles}`.trimEnd() + const id = props.params.RenderingIdentifier + + if (datasource) { + const list = datasource.children.results + .filter((element: ResultsFieldLink) => element?.field?.link) + .map((element: ResultsFieldLink, key: number) => ( + + )) + + return ( +
    +
    + +
      {list}
    +
    +
    + ) + } + + return ( +
    +
    +

    Link List

    +
    +
    + ) +} diff --git a/examples/cms-sitecore-xmcloud/src/components/Navigation.tsx b/examples/cms-sitecore-xmcloud/src/components/Navigation.tsx new file mode 100644 index 0000000000000..a96dba59bf4c2 --- /dev/null +++ b/examples/cms-sitecore-xmcloud/src/components/Navigation.tsx @@ -0,0 +1,170 @@ +import React, { useState } from 'react' +import { + Link, + LinkField, + Text, + TextField, + useSitecoreContext, +} from '@sitecore-jss/sitecore-jss-nextjs' + +interface Fields { + Id: string + DisplayName: string + Title: TextField + NavigationTitle: TextField + Href: string + Querystring: string + Children: Array + Styles: string[] +} + +type NavigationProps = { + params?: { [key: string]: string } + fields: Fields + handleClick: (event?: React.MouseEvent) => void + relativeLevel: number +} + +const getNavigationText = function ( + props: NavigationProps +): JSX.Element | string { + let text + + if (props.fields.NavigationTitle) { + text = + } else if (props.fields.Title) { + text = + } else { + text = props.fields.DisplayName + } + + return text +} + +const getLinkField = (props: NavigationProps): LinkField => ({ + value: { + href: props.fields.Href, + title: getLinkTitle(props), + querystring: props.fields.Querystring, + }, +}) + +export const Default = (props: NavigationProps): JSX.Element => { + const [isOpenMenu, openMenu] = useState(false) + const { sitecoreContext } = useSitecoreContext() + const styles = + props.params != null + ? `${props.params.GridParameters ?? ''} ${ + props.params.Styles ?? '' + }`.trimEnd() + : '' + const id = props.params != null ? props.params.RenderingIdentifier : null + + if (!Object.values(props.fields).length) { + return ( +
    +
    [Navigation]
    +
    + ) + } + + const handleToggleMenu = ( + event?: React.MouseEvent, + flag?: boolean + ): void => { + if (event && sitecoreContext?.pageEditing) { + event.preventDefault() + } + + if (flag !== undefined) { + return openMenu(flag) + } + + openMenu(!isOpenMenu) + } + + const list = Object.values(props.fields) + .filter((element) => element) + .map((element: Fields, key: number) => ( + ) => + handleToggleMenu(event, false) + } + relativeLevel={1} + /> + )) + + return ( +
    +
    ) } - -const NavigationList = (props: NavigationProps) => { - const { sitecoreContext } = useSitecoreContext() - - let children: JSX.Element[] = [] - if (props.fields.Children && props.fields.Children.length) { - children = props.fields.Children.map((element: Fields, index: number) => ( - - )) - } - - return ( -
  • -
    - - {getNavigationText(props)} - -
    - {children.length > 0 ?
      {children}
    : null} -
  • - ) -} - -const getLinkTitle = (props: NavigationProps): string | undefined => { - let title - if (props.fields.NavigationTitle?.value) { - title = props.fields.NavigationTitle.value.toString() - } else if (props.fields.Title?.value) { - title = props.fields.Title.value.toString() - } else { - title = props.fields.DisplayName - } - - return title -} diff --git a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts index dbe1925ac6bdf..866fad3f82489 100644 --- a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts +++ b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts @@ -9,7 +9,7 @@ import * as plugins from 'temp/page-props-factory-plugins' export const isServerSidePropsContext = function ( context: GetServerSidePropsContext | GetStaticPropsContext ): context is GetServerSidePropsContext { - return (context).req !== undefined + return (context as GetServerSidePropsContext).req !== undefined } export interface Plugin { diff --git a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/normal-mode.ts b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/normal-mode.ts index e58d8f12376d6..76892e88c3910 100644 --- a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/normal-mode.ts +++ b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/plugins/normal-mode.ts @@ -37,7 +37,6 @@ class NormalModePlugin implements Plugin { props.layoutData = await layoutService.fetchLayoutData( path, props.locale, - // eslint-disable-next-line prettier/prettier isServerSidePropsContext(context) ? (context as GetServerSidePropsContext).req : undefined, From 350d95e0fee3ae6185a45c64a33d3edba402cdea Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 26 Aug 2023 18:25:42 -0700 Subject: [PATCH 7/7] more lint --- examples/cms-sitecore-xmcloud/package.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/examples/cms-sitecore-xmcloud/package.json b/examples/cms-sitecore-xmcloud/package.json index a6e2e4a25503a..19be60eb7a576 100644 --- a/examples/cms-sitecore-xmcloud/package.json +++ b/examples/cms-sitecore-xmcloud/package.json @@ -1,7 +1,4 @@ { - "name": "xmcloud-nextjs-starter", - "description": "Application utilizing Sitecore JavaScript Services and Next.js", - "version": "21.1.6", "private": true, "config": { "appName": "xmcloud-nextjs-starter", @@ -20,10 +17,6 @@ "node": ">=12", "npm": ">=6" }, - "author": { - "name": "Sitecore Corporation", - "url": "https://jss.sitecore.com" - }, "repository": { "type": "git", "url": "git+https://github.com/sitecore/jss.git" @@ -31,7 +24,6 @@ "bugs": { "url": "https://github.com/sitecore/jss/issues" }, - "license": "Apache-2.0", "dependencies": { "@sitecore-jss/sitecore-jss-nextjs": "~21.1.6", "bootstrap": "^5.1.3",