├── .nvmrc ├── .prettierrc.json ├── .env.example ├── public ├── robots.txt ├── js_snippets_before_body_end.js ├── _redirects ├── js_snippets_head.js ├── _headers └── _headersCsp.json ├── .gitignore ├── src ├── assets │ ├── stylesheets │ │ ├── bootstrap5 │ │ │ ├── helpers │ │ │ │ ├── _clearfix.scss │ │ │ │ ├── _text-truncation.scss │ │ │ │ ├── _visually-hidden.scss │ │ │ │ ├── _vr.scss │ │ │ │ ├── _stretched-link.scss │ │ │ │ ├── _stacks.scss │ │ │ │ ├── _colored-links.scss │ │ │ │ ├── _ratio.scss │ │ │ │ └── _position.scss │ │ │ ├── mixins │ │ │ │ ├── _clearfix.scss │ │ │ │ ├── _lists.scss │ │ │ │ ├── _color-scheme.scss │ │ │ │ ├── _text-truncate.scss │ │ │ │ ├── _resize.scss │ │ │ │ ├── _container.scss │ │ │ │ ├── _alert.scss │ │ │ │ ├── _backdrop.scss │ │ │ │ ├── _image.scss │ │ │ │ ├── _box-shadow.scss │ │ │ │ ├── _reset-text.scss │ │ │ │ ├── _list-group.scss │ │ │ │ ├── _deprecate.scss │ │ │ │ ├── _transition.scss │ │ │ │ ├── _pagination.scss │ │ │ │ ├── _table-variants.scss │ │ │ │ └── _visually-hidden.scss │ │ │ ├── forms │ │ │ │ ├── _form-text.scss │ │ │ │ ├── _validation.scss │ │ │ │ └── _labels.scss │ │ │ ├── _forms.scss │ │ │ ├── _helpers.scss │ │ │ ├── bootstrap-utilities.scss │ │ │ ├── bootstrap-reboot.scss │ │ │ ├── _transitions.scss │ │ │ ├── _badge.scss │ │ │ ├── _grid.scss │ │ │ ├── _mixins.scss │ │ │ ├── _breadcrumb.scss │ │ │ ├── _placeholders.scss │ │ │ ├── _close.scss │ │ │ ├── _images.scss │ │ │ ├── bootstrap.scss │ │ │ └── _containers.scss │ │ ├── _variables.scss │ │ ├── fontawesome │ │ │ ├── _fixed-width.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── _core.scss │ │ │ ├── _stacked.scss │ │ │ ├── _animated.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _bordered-pulled.scss │ │ │ └── _path.scss │ │ ├── variables │ │ │ └── _responsive.scss │ │ ├── _mixins.scss │ │ └── _fontawesome.scss │ ├── images │ │ ├── favicon.png │ │ ├── arrow_next.svg │ │ ├── arrow_prev.svg │ │ ├── button_widget.svg │ │ ├── video_widget.svg │ │ ├── divider_widget.svg │ │ ├── redirect_obj.svg │ │ ├── testimonial_widget.svg │ │ ├── icon_widget.svg │ │ ├── feature_panel_widget.svg │ │ ├── section_widget.svg │ │ ├── tick_list_widget.svg │ │ ├── space_widget.svg │ │ ├── cookie_consent_icon.svg │ │ └── tick_list_item_widget.svg │ └── fonts │ │ ├── Manrope-Bold-700.woff2 │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── Manrope-Medium-500.woff2 │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── tracking.js ├── Widgets │ ├── FormContainerWidget │ │ ├── utils │ │ │ ├── isCustomType.js │ │ │ ├── getFieldName.js │ │ │ ├── validations │ │ │ │ ├── insideFormContainerValidation.js │ │ │ │ ├── typeValidation.js │ │ │ │ └── customFieldNameValidation.js │ │ │ ├── pseudoRandom32CharHex.js │ │ │ ├── scrollIntoView.js │ │ │ ├── getFormContainer.js │ │ │ └── isFieldNameUnique.js │ │ ├── FormContainerWidgetClass.js │ │ ├── FormContainerWidget.scss │ │ └── FormIdComponent.js │ ├── VimeoVideoWidget │ │ ├── VimeoVideoWidget.scss │ │ └── VimeoVideoWidgetClass.js │ ├── YoutubeVideoWidget │ │ ├── YoutubeVideoWidget.scss │ │ └── YoutubeVideoWidgetClass.js │ ├── SpaceWidget │ │ ├── SpaceWidgetClass.js │ │ ├── SpaceWidgetComponent.js │ │ └── SpaceWidgetEditingConfig.js │ ├── editingConfigs.js │ ├── DividerWidget │ │ ├── DividerWidgetClass.js │ │ ├── DividerWidgetComponent.js │ │ ├── DividerWidgetEditingConfig.js │ │ └── DividerWidget.scss │ ├── index.js │ ├── LinkWidget │ │ ├── LinkWidgetClass.js │ │ ├── LinkWidgetEditingConfig.js │ │ └── LinkWidgetComponent.js │ ├── GalleryWidget │ │ ├── GalleryWidgetClass.js │ │ └── GalleryWidgetEditingConfig.js │ ├── GroupWidget │ │ ├── GroupWidgetComponent.js │ │ ├── GroupWidgetClass.js │ │ └── GroupWidgetEditingConfig.js │ ├── JobOverviewWidget │ │ ├── JobOverviewWidgetClass.js │ │ └── JobOverviewWidgetEditingConfig.js │ ├── FactWidget │ │ ├── FactWidgetClass.js │ │ ├── FactWidgetComponent.js │ │ ├── FactWidgetEditingConfig.js │ │ └── FactWidget.scss │ ├── VideoWidget │ │ ├── VideoWidgetClass.js │ │ ├── videoPlaceholder.js │ │ ├── VideoWidgetEditingConfig.js │ │ └── VideoWidgetComponent.js │ ├── TickListWidget │ │ ├── TickListWidgetClass.js │ │ ├── TickListWidgetComponent.js │ │ ├── TickListWidget.scss │ │ └── TickListWidgetEditingConfig.js │ ├── ColumnWidget │ │ ├── ColumnWidgetEditingConfig.js │ │ └── ColumnWidgetClass.js │ ├── IconContainerWidget │ │ ├── IconContainerWidgetClass.js │ │ ├── IconContainerWidgetEditingConfig.js │ │ └── IconContainerWidgetComponent.js │ ├── PricingSpecWidget │ │ ├── PricingSpecWidgetEditingConfig.js │ │ ├── PricingSpecWidgetClass.js │ │ └── PricingSpecWidgetComponent.js │ ├── TextWidget │ │ ├── TextWidgetClass.js │ │ ├── TextWidgetComponent.js │ │ └── TextWidgetEditingConfig.js │ ├── LinkContainerWidget │ │ ├── LinkContainerWidgetClass.js │ │ ├── LinkContainerWidgetComponent.js │ │ ├── LinkContainerWidget.scss │ │ └── LinkContainerWidgetEditingConfig.js │ ├── TestimonialSliderWidget │ │ ├── TestimonialSliderWidgetClass.js │ │ └── TestimonialSliderWidgetEditingConfig.js │ ├── TickListItemWidget │ │ ├── TickListItemWidgetComponent.js │ │ ├── TickListItemWidgetClass.js │ │ └── TickListItemWidgetEditingConfig.js │ ├── EventOverviewWidget │ │ ├── EventOverviewWidgetClass.js │ │ └── EventOverviewWidgetEditingConfig.js │ ├── TableRowWidget │ │ ├── TableRowWidgetEditingConfig.js │ │ ├── TableRowWidgetClass.js │ │ └── TableRowWidgetComponent.js │ ├── BoxWidget │ │ ├── BoxWidgetClass.js │ │ ├── BoxWidgetComponent.js │ │ └── BoxWidgetEditingConfig.js │ ├── BlogOverviewWidget │ │ ├── BlogOverviewWidgetClass.js │ │ ├── BlogOverviewWidgetComponent.js │ │ └── BlogOverviewWidgetEditingConfig.js │ ├── ButtonWidget │ │ ├── ButtonWidgetClass.js │ │ └── ButtonWidgetComponent.js │ ├── FormHiddenFieldWidget │ │ ├── FormHiddenFieldWidgetClass.js │ │ └── FormHiddenFieldWidgetComponent.js │ ├── PriceWidget │ │ ├── PriceWidgetClass.js │ │ ├── PriceWidgetEditingConfig.js │ │ ├── PriceWidget.scss │ │ └── PriceWidgetComponent.js │ ├── ThumbnailGalleryWidget │ │ ├── ThumbnailGalleryWidgetClass.js │ │ └── ThumbnailGalleryWidgetEditingConfig.js │ ├── FeaturePanelWidget │ │ ├── FeaturePanelWidgetClass.js │ │ ├── FeaturePanelWidgetComponent.js │ │ └── FeaturePanelWidgetEditingConfig.js │ ├── FormButtonWidget │ │ ├── FormButtonWidgetClass.js │ │ ├── FormButtonWidgetComponent.js │ │ └── FormButtonWidgetEditingConfig.js │ ├── TableWidget │ │ └── TableWidgetClass.js │ ├── IconWidget │ │ ├── IconWidgetClass.js │ │ └── IconWidgetComponent.js │ ├── CarouselWidget │ │ ├── CarouselWidgetClass.js │ │ └── CarouselWidgetEditingConfig.js │ ├── ColumnContainerWidget │ │ ├── ColumnContainerWidgetClass.js │ │ ├── ColumnContainerWidgetEditingConfig.js │ │ └── ColumnContainerWidgetComponent.js │ ├── TestimonialWidget │ │ └── TestimonialWidgetClass.js │ ├── ThumbnailGalleryImageWidget │ │ ├── ThumbnailGalleryImageWidgetClass.js │ │ └── ThumbnailGalleryImageWidgetEditingConfig.js │ ├── HeadlineWidget │ │ ├── HeadlineWidgetClass.js │ │ └── HeadlineWidgetComponent.js │ ├── ImageWidget │ │ ├── ImageWidgetClass.js │ │ └── ImageWidgetComponent.js │ ├── FormCheckboxWidget │ │ └── FormCheckboxWidgetClass.js │ ├── SectionWidget │ │ ├── SectionWidgetClass.js │ │ └── SectionWidgetComponent.js │ ├── FormInputFieldWidget │ │ └── FormInputFieldWidgetClass.js │ ├── AddressWidget │ │ └── AddressWidgetClass.js │ ├── GoogleMapsWidget │ │ ├── GoogleMapsWidgetClass.js │ │ └── GoogleMapsWidget.scss │ └── PricingWidget │ │ └── PricingWidgetClass.js ├── Objs │ ├── RedirectToUi │ │ ├── RedirectToUiObjClass.js │ │ ├── RedirectToUiEditingConfig.js │ │ └── RedirectToUiComponent.js │ ├── editingConfigs.js │ ├── Video │ │ ├── VideoObjClass.js │ │ └── VideoEditingConfig.js │ ├── index.js │ ├── Redirect │ │ ├── RedirectObjClass.js │ │ ├── RedirectEditingConfig.js │ │ └── RedirectComponent.js │ ├── Page │ │ ├── PageComponent.js │ │ ├── PageObjClass.js │ │ └── PageEditingConfig.js │ ├── Homepage │ │ ├── HomepageComponent.js │ │ └── HomepageObjClass.js │ ├── LandingPage │ │ ├── LandingPageComponent.js │ │ ├── LandingPageObjClass.js │ │ └── LandingPageEditingConfig.js │ ├── Image │ │ ├── ImageObjClass.js │ │ └── ImageEditingConfig.js │ ├── Download │ │ ├── DownloadObjClass.js │ │ └── DownloadEditingConfig.js │ ├── SearchResults │ │ ├── SearchResultsObjClass.js │ │ ├── SearchResultsTagList.js │ │ ├── ShowMoreButton.js │ │ ├── SearchResultsEditingConfig.js │ │ └── SearchResultItem.scss │ ├── Author │ │ ├── AuthorObjClass.js │ │ ├── AuthorEditingConfig.js │ │ └── AuthorComponent.js │ ├── Blog │ │ ├── BlogObjClass.js │ │ ├── BlogComponent.js │ │ └── BlogEditingConfig.js │ ├── _defaultPageAttributes.js │ ├── _metadataAttributes.js │ ├── BlogPost │ │ └── BlogPostObjClass.js │ ├── Event │ │ └── EventObjClass.js │ └── Job │ │ └── JobObjClass.js ├── prerenderContent │ ├── filenameFromUrl.js │ ├── reportError.js │ ├── contentHash.js │ ├── generatePreloadDump.js │ ├── storeResult.js │ ├── generateHtml.js │ └── extendRedirects.js ├── utils │ ├── isImageObj.js │ ├── alignmentClassName.js │ ├── googleMapsApiKey.js │ ├── formatDate.js │ ├── navigateToBlogWithTag.js │ ├── placeholderCss.js │ ├── urlFromBinaryObj.js │ └── isVideoObj.js ├── Components │ ├── WrapIfClassName.js │ ├── ScrivitoExtensions │ │ ├── index.js │ │ └── IconEditorTab │ │ │ ├── SingleIcon.js │ │ │ └── IconSearchResults.js │ ├── Navigation │ │ ├── LandingPageNavigation.js │ │ ├── ScrollToNextSectionLink.js │ │ ├── NavigationSection.js │ │ ├── CollapseToggle.js │ │ └── Logo.js │ ├── SchemaDotOrg │ │ ├── dataFromAuthor.js │ │ ├── dataFromBlog.js │ │ ├── dataFromAddressWidget.js │ │ ├── dataFromBlogPost.js │ │ ├── dataFromEvent.js │ │ └── dataFromJob.js │ ├── InPlaceEditingPlaceholder.js │ ├── BlogPost │ │ ├── BlogPostDate.js │ │ ├── BlogPostMorePosts.js │ │ └── BlogPostTagList.js │ ├── Tracking.js │ ├── AnimateOnReveal.js │ ├── Icon.js │ ├── Footer.js │ ├── AuthorImage.js │ ├── CurrentPageMetadata.js │ └── CookieConsentContext.js ├── config │ ├── objClassForContentType.js │ ├── windowScrivito.js │ ├── index.js │ ├── history.js │ └── scrivito.js ├── scrivito_extensions.js ├── _scrivito_extensions.html ├── catch_all_index.html └── index.js ├── generator-scrivito ├── generators │ ├── obj │ │ └── templates │ │ │ ├── X.scss.ejs │ │ │ ├── XComponent.js.ejs │ │ │ ├── XObjClass.js.ejs │ │ │ └── XEditingConfig.js.ejs │ └── widget │ │ └── templates │ │ ├── X.scss.ejs │ │ ├── XWidgetEditingConfig.js.ejs │ │ ├── XWidgetClass.js.ejs │ │ └── XWidgetComponent.js.ejs ├── package.json └── app │ └── index.js ├── netlify.toml ├── .circleci └── config.yml └── LICENSE /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | SCRIVITO_TENANT=your_scrivito_tenant_id 2 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /scrivito/ 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | build.zip 3 | buildNode 4 | buildPrerendered 5 | node_modules 6 | tmp 7 | .env 8 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_clearfix.scss: -------------------------------------------------------------------------------- 1 | .clearfix { 2 | @include clearfix(); 3 | } 4 | -------------------------------------------------------------------------------- /src/tracking.js: -------------------------------------------------------------------------------- 1 | // This file is for executing JavaScript code after the user has given cookie consent. 2 | -------------------------------------------------------------------------------- /src/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/images/favicon.png -------------------------------------------------------------------------------- /generator-scrivito/generators/obj/templates/X.scss.ejs: -------------------------------------------------------------------------------- 1 | // Styles for <%= objClassName %> 2 | 3 | .<%= cssClassName %> { 4 | } 5 | -------------------------------------------------------------------------------- /generator-scrivito/generators/widget/templates/X.scss.ejs: -------------------------------------------------------------------------------- 1 | // Styles for <%= widgetClassName %> 2 | 3 | .<%= cssClassName %> { 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/fonts/Manrope-Bold-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/Manrope-Bold-700.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Manrope-Medium-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/Manrope-Medium-500.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scrivito/scrivito_example_app_js/HEAD/src/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_text-truncation.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Text truncation 3 | // 4 | 5 | .text-truncate { 6 | @include text-truncate(); 7 | } 8 | -------------------------------------------------------------------------------- /src/Widgets/FormContainerWidget/utils/isCustomType.js: -------------------------------------------------------------------------------- 1 | export function isCustomType(widget) { 2 | return !widget.attributeDefinitions().type || widget.get("type") === "custom"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Widgets/VimeoVideoWidget/VimeoVideoWidget.scss: -------------------------------------------------------------------------------- 1 | .vimeo-video-widget--fullsize-iframe { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | } 8 | -------------------------------------------------------------------------------- /src/Objs/RedirectToUi/RedirectToUiObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const RedirectToUi = Scrivito.provideObjClass("RedirectToUi", { 4 | attributes: {}, 5 | }); 6 | -------------------------------------------------------------------------------- /src/Widgets/YoutubeVideoWidget/YoutubeVideoWidget.scss: -------------------------------------------------------------------------------- 1 | .youtube-video-widget--fullsize-iframe { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | width: 100%; 6 | height: 100%; 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/stylesheets/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "variables/colors"; 2 | @import "variables/responsive"; 3 | 4 | $border-radius: 0 !default; 5 | $border-radius-lg: 0 !default; 6 | $border-radius-sm: 0 !default; 7 | -------------------------------------------------------------------------------- /public/js_snippets_before_body_end.js: -------------------------------------------------------------------------------- 1 | // This file is for executing JavaScript code immediately before the body element is closed. 2 | // Here you can, for example, let third-party code render additional markup. 3 | -------------------------------------------------------------------------------- /src/Objs/editingConfigs.js: -------------------------------------------------------------------------------- 1 | function importAll(r) { 2 | r.keys().forEach(r); 3 | } 4 | 5 | // import all *EditingConfig.js files under src/Objs/ 6 | importAll(require.context("./", true, /EditingConfig\.js$/)); 7 | -------------------------------------------------------------------------------- /src/prerenderContent/filenameFromUrl.js: -------------------------------------------------------------------------------- 1 | export function filenameFromUrl(url) { 2 | const { pathname } = new URL(url); 3 | if (pathname === "/") return "/index.html"; 4 | 5 | return `${pathname}.html`; 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/isImageObj.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function isImageObj(obj) { 4 | return ( 5 | obj instanceof Scrivito.Obj && obj.objClass() === "Image" && obj.get("blob") 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /src/Components/WrapIfClassName.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | export function WrapIfClassName({ className, children }) { 4 | return className ?
{children}
: children; 5 | } 6 | -------------------------------------------------------------------------------- /src/Objs/Video/VideoObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const Video = Scrivito.provideObjClass("Video", { 4 | attributes: { 5 | blob: "binary", 6 | tags: "stringlist", 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/Objs/index.js: -------------------------------------------------------------------------------- 1 | function importAll(r) { 2 | r.keys().forEach(r); 3 | } 4 | 5 | // import all *ObjClass.js and *Component.js files under src/Objs/ 6 | importAll(require.context("./", true, /(ObjClass|Component)\.js$/)); 7 | -------------------------------------------------------------------------------- /src/Widgets/SpaceWidget/SpaceWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const SpaceWidget = Scrivito.provideWidgetClass("SpaceWidget", { 4 | attributes: { 5 | size: "float", 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/Components/ScrivitoExtensions/index.js: -------------------------------------------------------------------------------- 1 | function importAll(r) { 2 | r.keys().forEach(r); 3 | } 4 | 5 | // import all js files under src/Components/ScrivitoExtensions/ 6 | importAll(require.context("./", true, /\.js$/)); 7 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_visually-hidden.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Visually hidden 3 | // 4 | 5 | .visually-hidden, 6 | .visually-hidden-focusable:not(:focus):not(:focus-within) { 7 | @include visually-hidden(); 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_vr.scss: -------------------------------------------------------------------------------- 1 | .vr { 2 | display: inline-block; 3 | align-self: stretch; 4 | width: 1px; 5 | min-height: 1em; 6 | background-color: currentColor; 7 | opacity: $hr-opacity; 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/fontawesome/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | @use "sass:math"; 4 | 5 | .#{$fa-css-prefix}-fw { 6 | width: math.div(18em, 14); 7 | text-align: center; 8 | } 9 | -------------------------------------------------------------------------------- /src/Objs/Redirect/RedirectObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const Redirect = Scrivito.provideObjClass("Redirect", { 4 | attributes: { 5 | title: "string", 6 | link: "link", 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/Widgets/editingConfigs.js: -------------------------------------------------------------------------------- 1 | function importAll(r) { 2 | r.keys().forEach(r); 3 | } 4 | 5 | // import all *WidgetEditingConfig.js files under src/Widgets/ 6 | importAll(require.context("./", true, /WidgetEditingConfig\.js$/)); 7 | -------------------------------------------------------------------------------- /src/assets/stylesheets/fontawesome/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { 5 | @include sr-only(); 6 | } 7 | .sr-only-focusable { 8 | @include sr-only-focusable(); 9 | } 10 | -------------------------------------------------------------------------------- /src/prerenderContent/reportError.js: -------------------------------------------------------------------------------- 1 | export function reportError(message, ...args) { 2 | // Report to your external error tracker here, like Honeybadger or Rollbar. 3 | console.log(` ❌ [reportError] ${message}`, ...args); 4 | } 5 | -------------------------------------------------------------------------------- /src/Widgets/DividerWidget/DividerWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const DividerWidget = Scrivito.provideWidgetClass("DividerWidget", { 4 | attributes: { 5 | showLogo: "boolean", 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/utils/alignmentClassName.js: -------------------------------------------------------------------------------- 1 | export function alignmentClassName(widgetAlignment) { 2 | if (widgetAlignment === "center") return "text-center"; 3 | if (widgetAlignment === "right") return "text-end"; 4 | 5 | return null; 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/googleMapsApiKey.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function googleMapsApiKey() { 4 | const root = Scrivito.Obj.root(); 5 | if (!root) return ""; 6 | 7 | return root.get("googleMapsApiKey"); 8 | } 9 | -------------------------------------------------------------------------------- /src/Objs/Page/PageComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("Page", ({ page }) => ( 5 | 6 | )); 7 | -------------------------------------------------------------------------------- /src/Widgets/index.js: -------------------------------------------------------------------------------- 1 | function importAll(r) { 2 | r.keys().forEach(r); 3 | } 4 | 5 | // import all *WidgetClass.js and *WidgetComponent.js files under src/Widgets/ 6 | importAll(require.context("./", true, /Widget(Class|Component)\.js$/)); 7 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start clearfix 2 | @mixin clearfix() { 3 | &::after { 4 | display: block; 5 | clear: both; 6 | content: ""; 7 | } 8 | } 9 | // scss-docs-end clearfix 10 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_lists.scss: -------------------------------------------------------------------------------- 1 | // Lists 2 | 3 | // Unstyled keeps list items block level, just removes default browser padding and list-style 4 | @mixin list-unstyled { 5 | padding-left: 0; 6 | list-style: none; 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/stylesheets/variables/_responsive.scss: -------------------------------------------------------------------------------- 1 | /* - BS3 variables - */ 2 | 3 | $screen-xs-max: 767px; 4 | $screen-sm-min: 768px; 5 | $screen-sm-max: 991px; 6 | $screen-md-min: 992px; 7 | $screen-md-max: 1199px; 8 | $screen-lg-min: 1200px; 9 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Global settings applied to the whole site. 2 | # “command” is your build command. 3 | # “publish” is the directory to publish (relative to root of your repo). 4 | 5 | [build] 6 | command = "npm run build" 7 | publish = "build" 8 | -------------------------------------------------------------------------------- /src/utils/formatDate.js: -------------------------------------------------------------------------------- 1 | import dateFormat from "dateformat"; 2 | 3 | export function formatDate(date, format) { 4 | // dateFormat uses Date.now if no date is given. 5 | if (!date) return null; 6 | 7 | return dateFormat(date, format); 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_color-scheme.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start mixin-color-scheme 2 | @mixin color-scheme($name) { 3 | @media (prefers-color-scheme: #{$name}) { 4 | @content; 5 | } 6 | } 7 | // scss-docs-end mixin-color-scheme 8 | -------------------------------------------------------------------------------- /src/Objs/Homepage/HomepageComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("Homepage", ({ page }) => ( 5 | 6 | )); 7 | -------------------------------------------------------------------------------- /src/Widgets/FormContainerWidget/utils/getFieldName.js: -------------------------------------------------------------------------------- 1 | import { isCustomType } from "./isCustomType"; 2 | 3 | export function getFieldName(widget) { 4 | return isCustomType(widget) 5 | ? widget.get("customFieldName") 6 | : widget.get("type"); 7 | } 8 | -------------------------------------------------------------------------------- /src/Widgets/LinkWidget/LinkWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const LinkWidget = Scrivito.provideWidgetClass("LinkWidget", { 4 | onlyInside: "LinkContainerWidget", 5 | attributes: { 6 | link: "link", 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_text-truncate.scss: -------------------------------------------------------------------------------- 1 | // Text truncate 2 | // Requires inline-block or block for proper styling 3 | 4 | @mixin text-truncate() { 5 | overflow: hidden; 6 | text-overflow: ellipsis; 7 | white-space: nowrap; 8 | } 9 | -------------------------------------------------------------------------------- /src/Objs/LandingPage/LandingPageComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("LandingPage", ({ page }) => ( 5 | 6 | )); 7 | -------------------------------------------------------------------------------- /src/Widgets/GalleryWidget/GalleryWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const GalleryWidget = Scrivito.provideWidgetClass("GalleryWidget", { 4 | attributes: { 5 | images: ["referencelist", { only: ["Image"] }], 6 | }, 7 | }); 8 | -------------------------------------------------------------------------------- /src/Widgets/GroupWidget/GroupWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("GroupWidget", ({ widget }) => ( 5 | 6 | )); 7 | -------------------------------------------------------------------------------- /src/Objs/Image/ImageObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const Image = Scrivito.provideObjClass("Image", { 4 | attributes: { 5 | blob: "binary", 6 | tags: "stringlist", 7 | alternativeText: "string", 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /src/Widgets/GroupWidget/GroupWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const GroupWidget = Scrivito.provideWidgetClass("GroupWidget", { 4 | attributes: { 5 | content: "widgetlist", 6 | }, 7 | extractTextAttributes: ["content"], 8 | }); 9 | -------------------------------------------------------------------------------- /src/utils/navigateToBlogWithTag.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function navigateToBlogWithTag(tag) { 4 | const params = {}; 5 | if (tag) params.tag = tag; 6 | 7 | Scrivito.navigateTo(() => Scrivito.Obj.getByPermalink("blog"), params); 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_resize.scss: -------------------------------------------------------------------------------- 1 | // Resize anything 2 | 3 | @mixin resizable($direction) { 4 | overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` 5 | resize: $direction; // Options: horizontal, vertical, both 6 | } 7 | -------------------------------------------------------------------------------- /src/Widgets/GroupWidget/GroupWidgetEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import groupWidgetIcon from "../../assets/images/group_widget.svg"; 3 | 4 | Scrivito.provideEditingConfig("GroupWidget", { 5 | title: "Group", 6 | thumbnail: groupWidgetIcon, 7 | }); 8 | -------------------------------------------------------------------------------- /src/utils/placeholderCss.js: -------------------------------------------------------------------------------- 1 | export const placeholderCss = { 2 | color: "rgba(64, 64, 64, 0.53)", 3 | display: "inline-block", 4 | fontSize: "13px", 5 | fontStyle: "normal", 6 | fontWeight: "normal", 7 | lineHeight: "28px", 8 | verticalAlign: "middle", 9 | }; 10 | -------------------------------------------------------------------------------- /src/prerenderContent/contentHash.js: -------------------------------------------------------------------------------- 1 | import { md4 } from "hash-wasm"; 2 | 3 | /** Generates a 20 long hex value, based the md4 of the given string */ 4 | export async function contentHash(input) { 5 | const md4OfInput = await md4(input); 6 | return md4OfInput.substring(0, 20); 7 | } 8 | -------------------------------------------------------------------------------- /generator-scrivito/generators/widget/templates/XWidgetEditingConfig.js.ejs: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | Scrivito.provideEditingConfig("<%= widgetClassName %>", { 4 | title: "<%= humanFriendlyName %>", 5 | initialContent: { 6 | headline: "Lorem Ipsum", 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/config/objClassForContentType.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function configureObjClassForContentType() { 4 | Scrivito.configureObjClassForContentType({ 5 | "image/*": "Image", 6 | "video/*": "Video", 7 | "*/*": "Download", 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | ## 2 | # Netlify redirect rules. See https://www.netlify.com/docs/redirects/ for details. 3 | ## 4 | 5 | # Single Page Application routes 6 | /* status-code=404-not-found /catch_all_index.html 404 7 | # PRERENDERED-UPPERCASE-ROUTES-PLACEHOLDER 8 | /* /catch_all_index.html 200 9 | -------------------------------------------------------------------------------- /src/Widgets/JobOverviewWidget/JobOverviewWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const JobOverviewWidget = Scrivito.provideWidgetClass( 4 | "JobOverviewWidget", 5 | { 6 | attributes: { 7 | locationLocality: "string", 8 | }, 9 | } 10 | ); 11 | -------------------------------------------------------------------------------- /src/Widgets/SpaceWidget/SpaceWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("SpaceWidget", ({ widget }) => { 5 | const size = widget.get("size") || 5; 6 | return
; 7 | }); 8 | -------------------------------------------------------------------------------- /src/Widgets/FactWidget/FactWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const FactWidget = Scrivito.provideWidgetClass("FactWidget", { 4 | attributes: { 5 | key: "string", 6 | value: "string", 7 | }, 8 | extractTextAttributes: ["key", "value"], 9 | }); 10 | -------------------------------------------------------------------------------- /src/Widgets/FormContainerWidget/utils/validations/insideFormContainerValidation.js: -------------------------------------------------------------------------------- 1 | import { getFormContainer } from "../getFormContainer"; 2 | 3 | export function insideFormContainerValidation(widget) { 4 | if (!getFormContainer(widget)) { 5 | return "Needs to be inside a form."; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Widgets/VideoWidget/VideoWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const VideoWidget = Scrivito.provideWidgetClass("VideoWidget", { 4 | attributes: { 5 | source: ["reference", { only: ["Video"] }], 6 | poster: ["reference", { only: ["Image"] }], 7 | }, 8 | }); 9 | -------------------------------------------------------------------------------- /src/config/windowScrivito.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function configureWindowScrivito() { 4 | if (typeof window === "undefined") return; 5 | 6 | // set Scrivito as a global to allow easier debugging in the javascript console. 7 | window.Scrivito = Scrivito; 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/urlFromBinaryObj.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function urlFromBinaryObj(binary) { 4 | if (!(binary instanceof Scrivito.Obj)) return null; 5 | 6 | const blob = binary.get("blob"); 7 | if (!blob) return null; 8 | 9 | return blob.url() || null; 10 | } 11 | -------------------------------------------------------------------------------- /src/Widgets/TickListWidget/TickListWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TickListWidget = Scrivito.provideWidgetClass("TickListWidget", { 4 | attributes: { 5 | items: ["widgetlist", { only: "TickListItemWidget" }], 6 | }, 7 | extractTextAttributes: ["items"], 8 | }); 9 | -------------------------------------------------------------------------------- /generator-scrivito/generators/widget/templates/XWidgetClass.js.ejs: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const <%= widgetClassName %> = Scrivito.provideWidgetClass("<%= widgetClassName %>", { 4 | attributes: { 5 | headline: "string", 6 | }, 7 | extractTextAttributes: ["headline"], 8 | }); 9 | -------------------------------------------------------------------------------- /src/Objs/Download/DownloadObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const Download = Scrivito.provideObjClass("Download", { 4 | attributes: { 5 | blob: "binary", 6 | tags: "stringlist", 7 | title: "string", 8 | }, 9 | extractTextAttributes: ["blob:text"], 10 | }); 11 | -------------------------------------------------------------------------------- /src/utils/isVideoObj.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export function isVideoObj(obj) { 4 | if (!(obj instanceof Scrivito.Obj)) return false; 5 | 6 | const contentType = obj.contentType(); 7 | if (!contentType) return false; 8 | 9 | return contentType.startsWith("video/"); 10 | } 11 | -------------------------------------------------------------------------------- /src/Widgets/ColumnWidget/ColumnWidgetEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import columnWidgetIcon from "../../assets/images/column_widget.svg"; 3 | 4 | Scrivito.provideEditingConfig("ColumnWidget", { 5 | title: "Column", 6 | thumbnail: columnWidgetIcon, 7 | hideInSelectionDialogs: true, 8 | }); 9 | -------------------------------------------------------------------------------- /src/Widgets/FormContainerWidget/utils/pseudoRandom32CharHex.js: -------------------------------------------------------------------------------- 1 | import { times } from "lodash-es"; 2 | 3 | export function pseudoRandom32CharHex() { 4 | return times(32).map(pseudoRandomHex).join(""); 5 | } 6 | 7 | function pseudoRandomHex() { 8 | return Math.floor(Math.random() * 16).toString(16); 9 | } 10 | -------------------------------------------------------------------------------- /src/Objs/RedirectToUi/RedirectToUiEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import redirectObjIcon from "../../assets/images/redirect_obj.svg"; 3 | 4 | Scrivito.provideEditingConfig("RedirectToUi", { 5 | title: "Redirect To UI", 6 | thumbnail: redirectObjIcon, 7 | hideInSelectionDialogs: true, 8 | }); 9 | -------------------------------------------------------------------------------- /src/Widgets/IconContainerWidget/IconContainerWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const IconContainerWidget = Scrivito.provideWidgetClass( 4 | "IconContainerWidget", 5 | { 6 | attributes: { 7 | iconList: ["widgetlist", { only: "IconWidget" }], 8 | }, 9 | } 10 | ); 11 | -------------------------------------------------------------------------------- /src/Widgets/PricingSpecWidget/PricingSpecWidgetEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import pricingSpecWidgetIcon from "../../assets/images/pricing_spec_widget.svg"; 3 | 4 | Scrivito.provideEditingConfig("PricingSpecWidget", { 5 | title: "Pricing Spec", 6 | thumbnail: pricingSpecWidgetIcon, 7 | }); 8 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/forms/_form-text.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Form text 3 | // 4 | 5 | .form-text { 6 | margin-top: $form-text-margin-top; 7 | @include font-size($form-text-font-size); 8 | font-style: $form-text-font-style; 9 | font-weight: $form-text-font-weight; 10 | color: $form-text-color; 11 | } 12 | -------------------------------------------------------------------------------- /src/Objs/Video/VideoEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | Scrivito.provideEditingConfig("Video", { 4 | attributes: { 5 | tags: { 6 | title: "Tags", 7 | description: "Make it easier to find this video by adding some tags.", 8 | }, 9 | }, 10 | properties: ["tags"], 11 | }); 12 | -------------------------------------------------------------------------------- /src/Widgets/TextWidget/TextWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TextWidget = Scrivito.provideWidgetClass("TextWidget", { 4 | attributes: { 5 | text: "html", 6 | alignment: ["enum", { values: ["left", "center", "right"] }], 7 | }, 8 | extractTextAttributes: ["text"], 9 | }); 10 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/_forms.scss: -------------------------------------------------------------------------------- 1 | @import "forms/labels"; 2 | @import "forms/form-text"; 3 | @import "forms/form-control"; 4 | @import "forms/form-select"; 5 | @import "forms/form-check"; 6 | @import "forms/form-range"; 7 | @import "forms/floating-labels"; 8 | @import "forms/input-group"; 9 | @import "forms/validation"; 10 | -------------------------------------------------------------------------------- /src/Widgets/FormContainerWidget/utils/scrollIntoView.js: -------------------------------------------------------------------------------- 1 | export function scrollIntoView(element) { 2 | window.scrollTo({ 3 | top: getTop(element) - 95, 4 | behavior: "smooth", 5 | }); 6 | } 7 | 8 | function getTop(element) { 9 | const rect = element.getBoundingClientRect(); 10 | return rect.top + window.pageYOffset; 11 | } 12 | -------------------------------------------------------------------------------- /src/Widgets/LinkContainerWidget/LinkContainerWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const LinkContainerWidget = Scrivito.provideWidgetClass( 4 | "LinkContainerWidget", 5 | { 6 | attributes: { 7 | headline: "string", 8 | links: ["widgetlist", { only: "LinkWidget" }], 9 | }, 10 | } 11 | ); 12 | -------------------------------------------------------------------------------- /src/Widgets/TestimonialSliderWidget/TestimonialSliderWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TestimonialSliderWidget = Scrivito.provideWidgetClass( 4 | "TestimonialSliderWidget", 5 | { 6 | attributes: { 7 | testimonials: ["widgetlist", { only: "TestimonialWidget" }], 8 | }, 9 | } 10 | ); 11 | -------------------------------------------------------------------------------- /src/Widgets/TickListItemWidget/TickListItemWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("TickListItemWidget", ({ widget }) => ( 5 | 6 | 7 | 8 | )); 9 | -------------------------------------------------------------------------------- /src/Components/Navigation/LandingPageNavigation.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { Logo } from "./Logo"; 3 | 4 | export function LandingPageNavigation({ navigationStyle }) { 5 | return ( 6 |
7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/Widgets/ColumnWidget/ColumnWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const ColumnWidget = Scrivito.provideWidgetClass("ColumnWidget", { 4 | onlyInside: "ColumnContainerWidget", 5 | attributes: { 6 | colSize: "integer", 7 | content: "widgetlist", 8 | }, 9 | extractTextAttributes: ["content"], 10 | }); 11 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/_helpers.scss: -------------------------------------------------------------------------------- 1 | @import "helpers/clearfix"; 2 | @import "helpers/colored-links"; 3 | @import "helpers/ratio"; 4 | @import "helpers/position"; 5 | @import "helpers/stacks"; 6 | @import "helpers/visually-hidden"; 7 | @import "helpers/stretched-link"; 8 | @import "helpers/text-truncation"; 9 | @import "helpers/vr"; 10 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_stretched-link.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Stretched link 3 | // 4 | 5 | .stretched-link { 6 | &::#{$stretched-link-pseudo-element} { 7 | position: absolute; 8 | top: 0; 9 | right: 0; 10 | bottom: 0; 11 | left: 0; 12 | z-index: $stretched-link-z-index; 13 | content: ""; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Widgets/EventOverviewWidget/EventOverviewWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const EventOverviewWidget = Scrivito.provideWidgetClass( 4 | "EventOverviewWidget", 5 | { 6 | attributes: { 7 | maxItems: "integer", 8 | showTags: "boolean", 9 | tags: "stringlist", 10 | }, 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Widgets/TableRowWidget/TableRowWidgetEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import tableRowWidgetIcon from "../../assets/images/table_row_widget.svg"; 3 | 4 | Scrivito.provideEditingConfig("TableRowWidget", { 5 | title: "Table Row", 6 | thumbnail: tableRowWidgetIcon, 7 | titleForContent: (widget) => widget.get("cell1"), 8 | }); 9 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_container.scss: -------------------------------------------------------------------------------- 1 | // Container mixins 2 | 3 | @mixin make-container($gutter: $container-padding-x) { 4 | width: 100%; 5 | padding-right: var(--#{$variable-prefix}gutter-x, #{$gutter}); 6 | padding-left: var(--#{$variable-prefix}gutter-x, #{$gutter}); 7 | margin-right: auto; 8 | margin-left: auto; 9 | } 10 | -------------------------------------------------------------------------------- /src/Widgets/BoxWidget/BoxWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const BoxWidget = Scrivito.provideWidgetClass("BoxWidget", { 4 | attributes: { 5 | body: "widgetlist", 6 | boxStyle: ["enum", { values: ["transparent", "white"] }], 7 | useOffset: "boolean", 8 | }, 9 | extractTextAttributes: ["body"], 10 | }); 11 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/helpers/_stacks.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start stacks 2 | .hstack { 3 | display: flex; 4 | flex-direction: row; 5 | align-items: center; 6 | align-self: stretch; 7 | } 8 | 9 | .vstack { 10 | display: flex; 11 | flex: 1 1 auto; 12 | flex-direction: column; 13 | align-self: stretch; 14 | } 15 | // scss-docs-end stacks 16 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_alert.scss: -------------------------------------------------------------------------------- 1 | // scss-docs-start alert-variant-mixin 2 | @mixin alert-variant($background, $border, $color) { 3 | color: $color; 4 | @include gradient-bg($background); 5 | border-color: $border; 6 | 7 | .alert-link { 8 | color: shade-color($color, 20%); 9 | } 10 | } 11 | // scss-docs-end alert-variant-mixin 12 | -------------------------------------------------------------------------------- /src/Widgets/BlogOverviewWidget/BlogOverviewWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const BlogOverviewWidget = Scrivito.provideWidgetClass( 4 | "BlogOverviewWidget", 5 | { 6 | attributes: { 7 | maxItems: "integer", 8 | author: ["reference", { only: "Author" }], 9 | tags: "stringlist", 10 | }, 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Widgets/TickListItemWidget/TickListItemWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TickListItemWidget = Scrivito.provideWidgetClass( 4 | "TickListItemWidget", 5 | { 6 | onlyInside: "TickListWidget", 7 | attributes: { 8 | statement: "string", 9 | }, 10 | extractTextAttributes: ["statement"], 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Widgets/ButtonWidget/ButtonWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const ButtonWidget = Scrivito.provideWidgetClass("ButtonWidget", { 4 | attributes: { 5 | target: "link", 6 | alignment: ["enum", { values: ["left", "center", "right", "block"] }], 7 | style: ["enum", { values: ["btn-primary", "btn-clear"] }], 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /src/Widgets/FormHiddenFieldWidget/FormHiddenFieldWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const FormHiddenFieldWidget = Scrivito.provideWidgetClass( 4 | "FormHiddenFieldWidget", 5 | { 6 | onlyInside: "FormContainerWidget", 7 | attributes: { 8 | customFieldName: "string", 9 | hiddenValue: "string", 10 | }, 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Widgets/PriceWidget/PriceWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const PriceWidget = Scrivito.provideWidgetClass("PriceWidget", { 4 | onlyInside: "TableRowWidget", 5 | attributes: { 6 | currency: "string", 7 | period: "string", 8 | price: "string", 9 | }, 10 | extractTextAttributes: ["price", "currency", "period"], 11 | }); 12 | -------------------------------------------------------------------------------- /src/Widgets/ThumbnailGalleryWidget/ThumbnailGalleryWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const ThumbnailGalleryWidget = Scrivito.provideWidgetClass( 4 | "ThumbnailGalleryWidget", 5 | { 6 | attributes: { 7 | images: ["widgetlist", { only: "ThumbnailGalleryImageWidget" }], 8 | showTags: "boolean", 9 | }, 10 | } 11 | ); 12 | -------------------------------------------------------------------------------- /src/Widgets/PriceWidget/PriceWidgetEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import priceWidgetIcon from "../../assets/images/price_widget.svg"; 3 | 4 | Scrivito.provideEditingConfig("PriceWidget", { 5 | title: "Price", 6 | thumbnail: priceWidgetIcon, 7 | initialContent: { 8 | currency: "$", 9 | price: "20", 10 | period: "/mo", 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /public/js_snippets_head.js: -------------------------------------------------------------------------------- 1 | // This file is for executing JavaScript code immediately before the head element is closed. 2 | // Here you can, for example, connect your site to remote services such as booking.com, segment.io, etc. 3 | // Don't forget to whitelist the URLs in the CSP at public/_headersCsp.json. 4 | 5 | // Intercom is already taken care of by the app, so there's no need to add it here. 6 | -------------------------------------------------------------------------------- /src/Widgets/TickListWidget/TickListWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | import "./TickListWidget.scss"; 5 | 6 | Scrivito.provideComponent("TickListWidget", ({ widget }) => ( 7 | 13 | )); 14 | -------------------------------------------------------------------------------- /src/Components/SchemaDotOrg/dataFromAuthor.js: -------------------------------------------------------------------------------- 1 | import { urlFromBinaryObj } from "../../utils/urlFromBinaryObj"; 2 | 3 | export function dataFromAuthor(author) { 4 | return { 5 | "@context": "http://schema.org", 6 | "@type": "Person", 7 | name: author.get("title"), 8 | description: author.get("description"), 9 | image: urlFromBinaryObj(author.get("image")), 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /src/Objs/SearchResults/SearchResultsObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import { metadataAttributes } from "../_metadataAttributes"; 3 | 4 | export const SearchResults = Scrivito.provideObjClass("SearchResults", { 5 | attributes: { 6 | title: "string", 7 | navigationBackgroundImage: ["reference", { only: ["Image"] }], 8 | ...metadataAttributes, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /src/Widgets/PricingSpecWidget/PricingSpecWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const PricingSpecWidget = Scrivito.provideWidgetClass( 4 | "PricingSpecWidget", 5 | { 6 | onlyInside: "PricingWidget", 7 | attributes: { 8 | variable: "string", 9 | unit: "string", 10 | }, 11 | extractTextAttributes: ["variable", "unit"], 12 | } 13 | ); 14 | -------------------------------------------------------------------------------- /src/Widgets/FeaturePanelWidget/FeaturePanelWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const FeaturePanelWidget = Scrivito.provideWidgetClass( 4 | "FeaturePanelWidget", 5 | { 6 | attributes: { 7 | icon: "string", 8 | headline: "string", 9 | description: "string", 10 | }, 11 | extractTextAttributes: ["headline", "description"], 12 | } 13 | ); 14 | -------------------------------------------------------------------------------- /generator-scrivito/generators/obj/templates/XComponent.js.ejs: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | import "./<%= objClassName %>.scss"; 5 | 6 | Scrivito.provideComponent("<%= objClassName %>", ({ page }) => ( 7 | 13 | )); 14 | -------------------------------------------------------------------------------- /src/Widgets/FormButtonWidget/FormButtonWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const FormButtonWidget = Scrivito.provideWidgetClass( 4 | "FormButtonWidget", 5 | { 6 | attributes: { 7 | buttonText: "string", 8 | alignment: ["enum", { values: ["left", "center", "right", "block"] }], 9 | }, 10 | extractTextAttributes: ["buttonText"], 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Widgets/PriceWidget/PriceWidget.scss: -------------------------------------------------------------------------------- 1 | .price-widget { 2 | margin-top: 10px; 3 | 4 | &--dollar { 5 | font-size: 24px; 6 | position: relative; 7 | top: -20px; 8 | } 9 | 10 | &--price { 11 | font-size: 50px; 12 | padding: 0 3px; 13 | } 14 | 15 | &--period { 16 | font-size: 14px; 17 | margin-left: 0; 18 | position: relative; 19 | top: -3px; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /generator-scrivito/generators/widget/templates/XWidgetComponent.js.ejs: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | import "./<%= widgetClassName %>.scss"; 5 | 6 | Scrivito.provideComponent("<%= widgetClassName %>", ({ widget }) => ( 7 | 12 | )); 13 | -------------------------------------------------------------------------------- /src/Widgets/VimeoVideoWidget/VimeoVideoWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const VimeoVideoWidget = Scrivito.provideWidgetClass( 4 | "VimeoVideoWidget", 5 | { 6 | attributes: { 7 | vimeoVideoId: "string", 8 | aspectRatio: [ 9 | "enum", 10 | { values: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"] }, 11 | ], 12 | }, 13 | } 14 | ); 15 | -------------------------------------------------------------------------------- /src/Widgets/YoutubeVideoWidget/YoutubeVideoWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const YoutubeVideoWidget = Scrivito.provideWidgetClass( 4 | "YoutubeVideoWidget", 5 | { 6 | attributes: { 7 | youtubeVideoId: "string", 8 | aspectRatio: [ 9 | "enum", 10 | { values: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"] }, 11 | ], 12 | }, 13 | } 14 | ); 15 | -------------------------------------------------------------------------------- /src/assets/stylesheets/_mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin transition-performance() { 2 | -webkit-backface-visibility: hidden; 3 | backface-visibility: hidden; 4 | -moz-osx-font-smoothing: grayscale; 5 | -webkit-backface-visibility: hidden; 6 | -webkit-transform: translateZ(0); 7 | -moz-transform: translateZ(0); 8 | -ms-transform: translateZ(0); 9 | -o-transform: translateZ(0); 10 | transform: translateZ(0); 11 | } 12 | -------------------------------------------------------------------------------- /src/Objs/Author/AuthorObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import { metadataAttributes } from "../_metadataAttributes"; 3 | 4 | export const Author = Scrivito.provideObjClass("Author", { 5 | attributes: { 6 | title: "string", 7 | description: "string", 8 | image: ["reference", { only: ["Image"] }], 9 | ...metadataAttributes, 10 | }, 11 | extractTextAttributes: ["description"], 12 | }); 13 | -------------------------------------------------------------------------------- /src/Objs/Page/PageObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import { metadataAttributes } from "../_metadataAttributes"; 3 | import { defaultPageAttributes } from "../_defaultPageAttributes"; 4 | 5 | export const Page = Scrivito.provideObjClass("Page", { 6 | attributes: { 7 | ...defaultPageAttributes, 8 | ...metadataAttributes, 9 | }, 10 | extractTextAttributes: ["navigationSection", "body"], 11 | }); 12 | -------------------------------------------------------------------------------- /src/Widgets/TableWidget/TableWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TableWidget = Scrivito.provideWidgetClass("TableWidget", { 4 | attributes: { 5 | rows: ["widgetlist", { only: "TableRowWidget" }], 6 | summaryRows: ["widgetlist", { only: "TableRowWidget" }], 7 | header1: "string", 8 | header2: "string", 9 | header3: "string", 10 | header4: "string", 11 | }, 12 | }); 13 | -------------------------------------------------------------------------------- /src/Widgets/IconWidget/IconWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const IconWidget = Scrivito.provideWidgetClass("IconWidget", { 4 | attributes: { 5 | icon: "string", 6 | size: [ 7 | "enum", 8 | { values: ["fa-1x", "fa-lg", "fa-2x", "fa-3x", "fa-4x", "fa-5x"] }, 9 | ], 10 | alignment: ["enum", { values: ["left", "center", "right"] }], 11 | link: "link", 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /src/Widgets/TextWidget/TextWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | import { alignmentClassName } from "../../utils/alignmentClassName"; 4 | 5 | Scrivito.provideComponent("TextWidget", ({ widget }) => ( 6 | 12 | )); 13 | -------------------------------------------------------------------------------- /generator-scrivito/generators/obj/templates/XObjClass.js.ejs: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import metadataAttributes from "../_metadataAttributes"; 3 | 4 | export const <%= objClassName %> = Scrivito.provideObjClass("<%= objClassName %>", { 5 | attributes: { 6 | title: "string", 7 | body: ["widgetlist", { only: "SectionWidget" }], 8 | ...metadataAttributes, 9 | }, 10 | extractTextAttributes: ["body"], 11 | }); 12 | -------------------------------------------------------------------------------- /src/Widgets/CarouselWidget/CarouselWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const CarouselWidget = Scrivito.provideWidgetClass("CarouselWidget", { 4 | attributes: { 5 | images: ["referencelist", { only: ["Image"] }], 6 | showDescription: "boolean", 7 | descriptionLogo: ["reference", { only: ["Image"] }], 8 | description: "widgetlist", 9 | }, 10 | extractTextAttributes: ["description"], 11 | }); 12 | -------------------------------------------------------------------------------- /src/Objs/Download/DownloadEditingConfig.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | Scrivito.provideEditingConfig("Download", { 4 | attributes: { 5 | tags: { 6 | title: "Tags", 7 | description: "Make it easier to find this download by adding some tags.", 8 | }, 9 | title: { 10 | title: "Title", 11 | description: "Limit to 55 characters.", 12 | }, 13 | }, 14 | properties: ["title", "tags"], 15 | }); 16 | -------------------------------------------------------------------------------- /src/Widgets/ColumnContainerWidget/ColumnContainerWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const ColumnContainerWidget = Scrivito.provideWidgetClass( 4 | "ColumnContainerWidget", 5 | { 6 | attributes: { 7 | columns: ["widgetlist", { only: "ColumnWidget" }], 8 | alignment: ["enum", { values: ["start", "center", "end", "stretch"] }], 9 | }, 10 | extractTextAttributes: ["columns"], 11 | } 12 | ); 13 | -------------------------------------------------------------------------------- /src/Objs/Blog/BlogObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import { metadataAttributes } from "../_metadataAttributes"; 3 | 4 | export const Blog = Scrivito.provideObjClass("Blog", { 5 | attributes: { 6 | title: "string", 7 | navigationBackgroundImage: ["reference", { only: ["Image"] }], 8 | body: ["widgetlist", { only: "SectionWidget" }], 9 | ...metadataAttributes, 10 | }, 11 | extractTextAttributes: ["body"], 12 | }); 13 | -------------------------------------------------------------------------------- /src/Objs/LandingPage/LandingPageObjClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | import { metadataAttributes } from "../_metadataAttributes"; 3 | import { defaultPageAttributes } from "../_defaultPageAttributes"; 4 | 5 | export const LandingPage = Scrivito.provideObjClass("LandingPage", { 6 | attributes: { 7 | ...defaultPageAttributes, 8 | ...metadataAttributes, 9 | }, 10 | extractTextAttributes: ["navigationSection", "body"], 11 | }); 12 | -------------------------------------------------------------------------------- /public/_headers: -------------------------------------------------------------------------------- 1 | ## 2 | # Netlify headers. See https://www.netlify.com/docs/headers-and-basic-auth/ for details. 3 | # 4 | # CSP-DIRECTIVES-PLACEHOLDER will be replaced by webpack, which uses _headersCsp.json as input. 5 | ## 6 | 7 | /* 8 | Content-Security-Policy: CSP-DIRECTIVES-PLACEHOLDER 9 | X-Frame-Options: sameorigin 10 | X-XSS-Protection: 1; mode=block 11 | X-Content-Type-Options: nosniff 12 | Referrer-Policy: strict-origin-when-cross-origin 13 | -------------------------------------------------------------------------------- /src/Objs/_defaultPageAttributes.js: -------------------------------------------------------------------------------- 1 | export const defaultPageAttributes = { 2 | body: ["widgetlist", { only: "SectionWidget" }], 3 | navigationBackgroundImage: ["reference", { only: ["Image", "Video"] }], 4 | navigationBackgroundImageGradient: "boolean", 5 | navigationHeight: [ 6 | "enum", 7 | { 8 | values: ["small", "medium-height", "full-height"], 9 | }, 10 | ], 11 | navigationSection: "widgetlist", 12 | title: "string", 13 | }; 14 | -------------------------------------------------------------------------------- /src/Widgets/FormHiddenFieldWidget/FormHiddenFieldWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | import { getFieldName } from "../FormContainerWidget/utils/getFieldName"; 4 | 5 | Scrivito.provideComponent("FormHiddenFieldWidget", ({ widget }) => { 6 | const name = getFieldName(widget); 7 | if (!name) return null; 8 | 9 | return ; 10 | }); 11 | -------------------------------------------------------------------------------- /src/Widgets/TestimonialWidget/TestimonialWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const TestimonialWidget = Scrivito.provideWidgetClass( 4 | "TestimonialWidget", 5 | { 6 | onlyInside: "TestimonialSliderWidget", 7 | attributes: { 8 | testimonial: "string", 9 | author: "string", 10 | authorImage: ["reference", { only: ["Image"] }], 11 | }, 12 | extractTextAttributes: ["testimonial"], 13 | } 14 | ); 15 | -------------------------------------------------------------------------------- /src/assets/stylesheets/bootstrap5/mixins/_backdrop.scss: -------------------------------------------------------------------------------- 1 | // Shared between modals and offcanvases 2 | @mixin overlay-backdrop($zindex, $backdrop-bg, $backdrop-opacity) { 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | z-index: $zindex; 7 | width: 100vw; 8 | height: 100vh; 9 | background-color: $backdrop-bg; 10 | 11 | // Fade for backdrop 12 | &.fade { 13 | opacity: 0; 14 | } 15 | &.show { 16 | opacity: $backdrop-opacity; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Widgets/ThumbnailGalleryImageWidget/ThumbnailGalleryImageWidgetClass.js: -------------------------------------------------------------------------------- 1 | import * as Scrivito from "scrivito"; 2 | 3 | export const ThumbnailGalleryImageWidget = Scrivito.provideWidgetClass( 4 | "ThumbnailGalleryImageWidget", 5 | { 6 | onlyInside: "ThumbnailGalleryWidget", 7 | attributes: { 8 | image: ["reference", { only: ["Image"] }], 9 | title: "string", 10 | subtitle: "string", 11 | tags: "stringlist", 12 | }, 13 | } 14 | ); 15 | -------------------------------------------------------------------------------- /src/Widgets/PricingSpecWidget/PricingSpecWidgetComponent.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import * as Scrivito from "scrivito"; 3 | 4 | Scrivito.provideComponent("PricingSpecWidget", ({ widget }) => ( 5 |
6 | 12 | 13 |
14 | )); 15 | -------------------------------------------------------------------------------- /src/Components/Navigation/ScrollToNextSectionLink.js: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | export function ScrollToNextSectionLink({ heightClassName }) { 4 | if (heightClassName !== "full-height") return null; 5 | 6 | return ( 7 | 12 |