1"use strict";(self.webpackChunk_cromwell_website=self.webpackChunk_cromwell_website||[]).push([[8758],{7181:function(e,t,n){n.r(t),n.d(t,{frontMatter:function(){return s},contentTitle:function(){return l},metadata:function(){return p},toc:function(){return c},default:function(){return u}});var o=n(5773),a=n(808),r=(n(7378),n(5318)),i=["components"],s={title:"Toolkits intro",sidebar_position:1},l="Toolkits intro",p={unversionedId:"toolkits/intro",id:"toolkits/intro",isDocsHomePage:!1,title:"Toolkits intro",description:"Cromwell CMS toolkits are packages that help you build specific kinds of websites.",source:"@site/docs/toolkits/intro.md",sourceDirName:"toolkits",slug:"/toolkits/intro",permalink:"/docs/toolkits/intro",tags:[],version:"current",sidebarPosition:1,frontMatter:{title:"Toolkits intro",sidebar_position:1},sidebar:"tutorialSidebar",previous:{title:"Importer",permalink:"/docs/api/classes/frontend.Importer"},next:{title:"Commerce",permalink:"/docs/toolkits/commerce"}},c=[{value:"Customization",id:"customization",children:[{value:"1. <code>classes</code>",id:"1-classes",children:[]},{value:"2. <code>elements</code>",id:"2-elements",children:[]},{value:"3. <code>text</code>",id:"3-text",children:[]}]},{value:"Data fetching",id:"data-fetching",children:[{value:"<code>withGetProps</code>",id:"withgetprops",children:[]},{value:"<code>getData</code>",id:"getdata",children:[]},{value:"<code>useData</code>",id:"usedata",children:[]}]}],d={toc:c};function u(e){var t=e.components,n=(0,a.Z)(e,i);return(0,r.kt)("wrapper",(0,o.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"toolkits-intro"},"Toolkits intro"),(0,r.kt)("p",null,"Cromwell CMS toolkits are packages that help you build specific kinds of websites.",(0,r.kt)("br",{parentName:"p"}),"\n","Usually they provide frontend components that deal with CMS API and data structures,\napply some toolkit-specific logic, such as managing user cart or checkout process.",(0,r.kt)("br",{parentName:"p"}),"\n","That helps to abstract away Cromwell CMS specifics and allow developers to focus more",(0,r.kt)("br",{parentName:"p"}),"\n","on their apps and UI/UX design. "),(0,r.kt)("p",null,"Toolkit components are highly customizable via props and can work with different UI frameworks.",(0,r.kt)("br",{parentName:"p"}
1),"\n","And also to simplify usage toolkits also can provide ",(0,r.kt)("a",{parentName:"p",href:"https://reactjs.org/docs/higher-order-components.html"},"HOCs")," for specific frameworks or libraries.",(0,r.kt)("br",{parentName:"p"}),"\n","On pages of toolkits you will find a list of base components and a list of additional HOCs that style these\nbase components, but have the same props API.",(0,r.kt)("br",{parentName:"p"}),"\n","For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"commerce")," toolkit has Material UI versions of all basic components: "),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// Use base `Breadcrumbs` component \nimport { Breadcrumbs } from '@cromwell/toolkit-commerce';\n// Use `Breadcrumbs` HOC with Material UI elements.\nimport { MuiBreadcrumbs } from '@cromwell/toolkit-commerce';\n")),(0,r.kt)("h2",{id:"customization"},"Customization"),(0,r.kt)("p",null,"All components follow the same rules for customization via props. There are 3 common props\n(though not all components have all 3):"),(0,r.kt)("h3",{id:"1-classes"},"1. ",(0,r.kt)("inlineCode",{parentName:"h3"},"classes")),(0,r.kt)("p",null,"Object with custom CSS classes to assign on inner elements of a component:",(0,r.kt)("br",{parentName:"p"}),"\n",(0,r.kt)("inlineCode",{parentName:"p"},"{ [target_class]: 'your_class' }"),(0,r.kt)("br",{parentName:"p"}),"\n","You can use any styling solution to create your CSS classes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},"<MuiBreadcrumbs classes={{ link: 'breadcrumbLink' }} />\n")),(0,r.kt)("p",null,"When you browse DOM tree in developer tools you will find already assigned class names that follow the pattern:\n",(0,r.kt)("inlineCode",{parentName:"p"},"{packageName}_{fileNameHash}_{elementName}"),". For example, if you want to style element with CSS class ",(0,r.kt)("inlineCode",{parentName:"p"},"ccom_tktfs_link"),", you need to use ",(0,r.kt)("inlineCode",{parentName:"p"},"link")," in ",(0,r.kt)("inlineCode",{parentName:"p"},"classes")," prop.\nYou also can simply override ",(0,r.kt)("inlineCode",{parentName:"p"},".ccom_tktfs_link")," in your global CSS. Hash is created upon ",(0,r.kt)("inlineCode",{parentName:"p"},"["),"name of the file + package name",(0,r.kt)("inlineCode",{parentName:"p"},"]"),", so it won't change in the future."),(0,r.kt)("h3",{id:"2-elements"},"2. ",(0,r.kt)("inlineCode",{parentName:"h3"},"elements")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"elements")," are custom React components that display specific inner elements. Elements may have logic or\nmay need to be interactive, that's why in some cases we need to use ",(0,r.kt)("inlineCode",{parentName:"p"},"elements")," instead of ",(0,r.kt)("inlineCode",{parentName:"p"},"classes"),". "),(0,r.kt)("p",null,"For example, when you use base ",(0,r.kt)("inlineCode",{parentName:"p"},"ProductCard")," component, you can see product rating displayed simply\nas number ",(0,r.kt)("inlineCode",{parentName:"p"},"4"),". But if you use MuiProductCard, rating will be displayed as 4 bright star icons and 1 hollow.",(0,r.kt)("br",{parentName:"p"}),"\n","You can override ",(0,r.kt)("inlineCode",{parentName:"p"},"Rating")," element of MUI MuiProductCard, or if you don't want to bundle MUI at all, you can use base ProductCard and pass custom ",(0,r.kt)("inlineCode",{parentName:"p"},"Rating"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},"<ProductCard elements={{ \n Rating: ({ value }) => /** Return your JSX */ \n}} />\n")),(0,r.kt)("h3",{id:"3-text"},"3. ",(0,r.kt)("inlineCode",{parentName:"h3"},"text")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"text")," allows you to override any text used inside a component. Use it with your internalization solution\nto translate components in other languages.",(0,r.kt)("br",{parentName:"p"}),"\n","For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"Checkout"),' component displays checkout headers in English such as: "Shipping address".\nOverride headers in ',(0,r.kt)("inlineCode",{parentName:"p"},"text")," prop: "),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx"},"<Checkout text={{\n shippingAddress: 'Adresse de livraison'\n}} />\n")),(0,r.kt)("h2",{id:"data-fetching"}
1,"Data fetching"),(0,r.kt)("p",null,"Components that fetch data only on client will work out of the box. But some components require to\nsetup data fetching, so they could be pre-rendered on the backend."),(0,r.kt)("h3",{id:"withgetprops"},(0,r.kt)("inlineCode",{parentName:"h3"},"withGetProps")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"withGetProps")," is a wrapper for any of your Next.js data fetching methods such as: ",(0,r.kt)("inlineCode",{parentName:"p"},"getStaticProps"),",\n",(0,r.kt)("inlineCode",{parentName:"p"},"getServerSideProps"),".",(0,r.kt)("br",{parentName:"p"}),"\n",(0,r.kt)("inlineCode",{parentName:"p"},"withGetProps")," can be available as a property on a component. For example, for ",(0,r.kt)("inlineCode",{parentName:"p"},"Breadcrumbs"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx",metastring:'title="product/[slug].tsx"',title:'"product/[slug].tsx"'},"import { MuiBreadcrumbs } from '@cromwell/toolkit-commerce';\nimport { TGetStaticProps } from '@cromwell/core';\nimport React from 'react';\n\ntype ProductProps = {\n /* ... */\n}\n\nconst ProductPage: TCromwellPage<ProductProps> = (props) => { \n return (\n <div>\n <MuiBreadcrumbs />\n /* ... */\n </div>\n )\n}\n\nexport default ProductPage;\n\nconst getProps: TGetStaticProps<ProductProps> = async (context) => {\n /* fetch product */\n}\n\nexport const getStaticProps = MuiBreadcrumbs.withGetProps(getProps);\n")),(0,r.kt)("p",null,"As you see we only needed to wrap ",(0,r.kt)("inlineCode",{parentName:"p"},"getProps"),", no other action needed. ",(0,r.kt)("inlineCode",{parentName:"p"},"MuiBreadcrumbs")," will get its data\nfrom context on the frontend."),(0,r.kt)("h3",{id:"getdata"},(0,r.kt)("inlineCode",{parentName:"h3"},"getData")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"getData")," exposes data fetching method. For example, if you don't want to fetch data server-side via ",(0,r.kt)("inlineCode",{parentName:"p"},"withGetProps"),", you can use ",(0,r.kt)("inlineCode",{parentName:"p"},"getData")," and pass data as a prop."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx",metastring:'title="product/[slug].tsx"',title:'"product/[slug].tsx"'},"import { MuiBreadcrumbs } from '@cromwell/toolkit-commerce';\nimport { TGetStaticProps } from '@cromwell/core';\nimport React, { useEffect } from 'react';\n\nconst ProductPage: TCromwellPage = () => {\n const [breadcrumbsData, setBreadcrumbsData] = useState();\n\n useEffect(() => {\n MuiBreadcrumbs.getData({ productId: 1 }).then(data => \n setBreadcrumbsData(data));\n }, []);\n\n return (\n <div>\n <MuiBreadcrumbs data={breadcrumbsData} />\n /* ... */\n </div>\n )\n}\n\nexport default ProductPage;\n")),(0,r.kt)("h3",{id:"usedata"},(0,r.kt)("inlineCode",{parentName:"h3"},"useData")),(0,r.kt)("p",null,"If data was fetched via ",(0,r.kt)("inlineCode",{parentName:"p"},"withGetProps")," you can access it via ",(0,r.kt)("inlineCode",{parentName:"p"},"useData")," hook:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-tsx",metastring:'title="category/[slug].tsx"',title:'"category/[slug].tsx"'},"import { MuiCategoryList } from '@cromwell/toolkit-commerce';\nimport { TGetStaticProps } from '@cromwell/core';\nimport React from 'react';\n\nconst CategoryPage: TCromwellPage = () => { \n const categoryData = MuiCategoryList.useData();\n\n return (\n <div>\n <h1>{categoryData?.category?.name ?? ''}</h1>\n <MuiCategoryList />\n </div>\n )\n}\n\nexport default CategoryPage;\n\nexport const getStaticProps = MuiCategoryList.withGetProps();\n")))}u.isMDXComponent=!0},5318:function(e,t,n){n.d(t,{Zo:function(){return c},kt:function(){return m}});var o=n(7378);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};
1t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function s(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},r=Object.keys(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=o.createContext({}),p=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return o.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),m=a,k=u["".concat(l,".").concat(m)]||u[m]||d[m]||r;return n?o.createElement(k,i(i({ref:t},c),{},{components:n})):o.createElement(k,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var p=2;p<r;p++)i[p]=n[p];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}u.displayName="MDXCreateElement"}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.