@graphcommerce/docs 8.1.0-canary.3 → 8.1.0-canary.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -2
- package/framework/config.md +17 -3
- package/framework/plugins-react.md +154 -106
- package/magento/multi-theme-multi-website.md +130 -0
- package/package.json +2 -2
- package/upgrading/graphcommerce-8-to-9.md +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,63 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## 8.1.0-canary.
|
|
3
|
+
## 8.1.0-canary.5
|
|
4
4
|
|
|
5
|
-
## 8.
|
|
5
|
+
## 8.0.6-canary.4
|
|
6
|
+
|
|
7
|
+
## 8.0.6-canary.3
|
|
8
|
+
|
|
9
|
+
## 8.0.6-canary.2
|
|
10
|
+
|
|
11
|
+
## 8.0.6-canary.1
|
|
12
|
+
|
|
13
|
+
## 8.0.6-canary.0
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#2196](https://github.com/graphcommerce-org/graphcommerce/pull/2196) [`84c50e4`](https://github.com/graphcommerce-org/graphcommerce/commit/84c50e49a1a7f154d4a8f4045c37e773e20283ad) - Allow Lingui to use linguiLocale with country identifiers like `en-us`, it would always load `en` in this case. Introced a new `useLocale` hook to use the correct locale string to use in Intl methods.
|
|
18
|
+
([@paales](https://github.com/paales))
|
|
19
|
+
|
|
20
|
+
## 8.0.5
|
|
21
|
+
|
|
22
|
+
## 8.0.5-canary.10
|
|
23
|
+
|
|
24
|
+
## 8.0.5-canary.9
|
|
25
|
+
|
|
26
|
+
## 8.0.5-canary.8
|
|
27
|
+
|
|
28
|
+
## 8.0.5-canary.7
|
|
29
|
+
|
|
30
|
+
## 8.0.5-canary.6
|
|
31
|
+
|
|
32
|
+
## 8.0.5-canary.5
|
|
33
|
+
|
|
34
|
+
## 8.0.5-canary.4
|
|
35
|
+
|
|
36
|
+
## 8.0.5-canary.3
|
|
37
|
+
|
|
38
|
+
## 8.0.5-canary.2
|
|
39
|
+
|
|
40
|
+
## 8.0.5-canary.1
|
|
41
|
+
|
|
42
|
+
## 8.0.5-canary.0
|
|
43
|
+
|
|
44
|
+
## 8.0.4
|
|
45
|
+
|
|
46
|
+
## 8.0.4-canary.1
|
|
47
|
+
|
|
48
|
+
## 8.0.4-canary.0
|
|
49
|
+
|
|
50
|
+
## 8.0.3
|
|
51
|
+
|
|
52
|
+
## 8.0.3-canary.6
|
|
53
|
+
|
|
54
|
+
## 8.0.3-canary.5
|
|
55
|
+
|
|
56
|
+
## 8.0.3-canary.4
|
|
57
|
+
|
|
58
|
+
## 8.0.3-canary.3
|
|
59
|
+
|
|
60
|
+
## 8.0.3-canary.2
|
|
6
61
|
|
|
7
62
|
## 8.0.3-canary.1
|
|
8
63
|
|
package/framework/config.md
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
<!-- Automatically generated from Config.graphqls -->
|
|
2
|
+
### DatalayerConfig
|
|
3
|
+
|
|
4
|
+
GoogleDatalayerConfig to allow enabling certain aspects of the datalayer
|
|
5
|
+
|
|
6
|
+
#### coreWebVitals: boolean
|
|
7
|
+
|
|
8
|
+
Enable core web vitals tracking for GraphCommerce
|
|
9
|
+
|
|
2
10
|
# GraphCommerce configuration system
|
|
3
11
|
|
|
4
12
|
Global GraphCommerce configuration can be configured in your `graphcommerce.config.js` file
|
|
@@ -58,7 +66,7 @@ Examples:
|
|
|
58
66
|
|
|
59
67
|
You can export configuration by running `yarn graphcommerce export-config`
|
|
60
68
|
|
|
61
|
-
## Extending the configuration in your
|
|
69
|
+
## Extending the configuration in your project
|
|
62
70
|
|
|
63
71
|
Create a graphql/Config.graphqls file in your project and extend the GraphCommerceConfig, GraphCommerceStorefrontConfig inputs to add configuration.
|
|
64
72
|
|
|
@@ -159,6 +167,8 @@ customer requires email confirmation.
|
|
|
159
167
|
This value should match Magento 2's configuration value for
|
|
160
168
|
`customer/create_account/confirm` and should be removed once we can query
|
|
161
169
|
|
|
170
|
+
#### dataLayer: [DatalayerConfig](#DatalayerConfig)
|
|
171
|
+
|
|
162
172
|
#### debug: [GraphCommerceDebugConfig](#GraphCommerceDebugConfig)
|
|
163
173
|
|
|
164
174
|
Debug configuration for GraphCommerce
|
|
@@ -334,7 +344,9 @@ All storefront configuration for the project
|
|
|
334
344
|
|
|
335
345
|
#### locale: string (required)
|
|
336
346
|
|
|
337
|
-
Must be a locale string
|
|
347
|
+
Must be a [locale string](https://www.unicode.org/reports/tr35/tr35-59/tr35.html#Identifiers) for automatic redirects to work.
|
|
348
|
+
|
|
349
|
+
This value can be used as a sub-path identifier only, make sure linguiLocale is configured for each URL.
|
|
338
350
|
|
|
339
351
|
#### magentoStoreCode: string (required)
|
|
340
352
|
|
|
@@ -390,7 +402,9 @@ Add a gcms-locales header to make sure queries return in a certain language, can
|
|
|
390
402
|
|
|
391
403
|
#### linguiLocale: string
|
|
392
404
|
|
|
393
|
-
Specify a custom locale for to load translations.
|
|
405
|
+
Specify a custom locale for to load translations. Must be lowercase valid locale.
|
|
406
|
+
|
|
407
|
+
This value is also used for the Intl.
|
|
394
408
|
|
|
395
409
|
### MagentoConfigurableVariantValues
|
|
396
410
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Plugins GraphCommerce
|
|
2
2
|
|
|
3
|
-
GraphCommerce's plugin system allows you to extend GraphCommerce's
|
|
4
|
-
components or functions with your own logic.
|
|
3
|
+
GraphCommerce's plugin system allows you to extend or replace GraphCommerce's
|
|
4
|
+
built-in components or functions with your own logic.
|
|
5
5
|
|
|
6
6
|
- No runtime overhead: The plugin system is fully implemented in webpack and
|
|
7
7
|
- Easy plugin creation: Configuration should happen in the plugin file, not a
|
|
@@ -13,10 +13,11 @@ components or functions with your own logic.
|
|
|
13
13
|
A plugin is a way to modify React Components or a Function by wrapping them,
|
|
14
14
|
without having to modify the code directly.
|
|
15
15
|
|
|
16
|
-
For the M2 people: Think of around plugins, but without configuration files
|
|
17
|
-
no performance penalty.
|
|
16
|
+
> For the M2 people: Think of around plugins, but without configuration files
|
|
17
|
+
> and no performance penalty.
|
|
18
18
|
|
|
19
|
-
GraphCommerce has
|
|
19
|
+
GraphCommerce has three kinds of plugins, component plugins, function plugins
|
|
20
|
+
and replacement plugins.
|
|
20
21
|
|
|
21
22
|
React Component plugins, which can be used to:
|
|
22
23
|
|
|
@@ -33,103 +34,117 @@ Function plugins, which can be used to:
|
|
|
33
34
|
- Modify the arguments of a function
|
|
34
35
|
- Skip calling the original function conditionally
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
Replacement plugins, which can be used to:
|
|
38
|
+
|
|
39
|
+
- Replace any export with your own implementation
|
|
40
|
+
- Replace an internal component used by another internal component with your own
|
|
41
|
+
implementation.
|
|
42
|
+
|
|
43
|
+
## How do I write a component plugin?
|
|
37
44
|
|
|
38
45
|
In this example we're going to add some text to list items, just like the text
|
|
39
46
|
‘BY GC’ that can seen in the demo on
|
|
40
47
|
[category pages](https://graphcommerce.vercel.app/en/women/business).
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
```tsx
|
|
46
|
-
import type { ProductListItem } from '@graphcommerce/magento-product'
|
|
47
|
-
import type { ReactPlugin } from '@graphcommerce/next-config'
|
|
48
|
-
import { Typography } from '@mui/material'
|
|
49
|
-
|
|
50
|
-
export const component = 'ProductListItem' // Component to extend, required
|
|
51
|
-
export const exported = '@graphcommerce/magento-product' // Location where the component is exported, required
|
|
52
|
-
|
|
53
|
-
const ListPlugin: ReactPlugin<typeof ProductListItem> = (props) => {
|
|
54
|
-
// Prev in this case is ProductListItem, you should be able to see this if you log it.
|
|
55
|
-
const { Prev, ...rest } = props
|
|
56
|
-
return (
|
|
57
|
-
<Prev
|
|
58
|
-
{...rest}
|
|
59
|
-
subTitle={
|
|
60
|
-
<Typography component='span' variant='caption'>
|
|
61
|
-
Plugin!
|
|
62
|
-
</Typography>
|
|
63
|
-
}
|
|
64
|
-
/>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
export const Plugin = ListPlugin // An export with the name Plugin, required
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
2. Trigger the 'interceptor generation' so GraphCommerce knows of the existence
|
|
71
|
-
of your plugin. To enable: Modify the page that you expect the plugin to
|
|
72
|
-
occur on. In this case modify `pages/[...url].tsx` by adding a few linebreaks
|
|
73
|
-
and save the file
|
|
74
|
-
|
|
75
|
-
If everything went as expected you should see `Plugin!` below the product
|
|
76
|
-
name. If that doesn't work try restarting the dev server.
|
|
77
|
-
|
|
78
|
-
3. Happy programming!
|
|
79
|
-
|
|
80
|
-
4. You can enable debug mode in your graphcommerce.config.js:
|
|
81
|
-
|
|
82
|
-
```js
|
|
83
|
-
const config = {
|
|
84
|
-
debug: {
|
|
85
|
-
pluginStatus: true,
|
|
86
|
-
},
|
|
87
|
-
}
|
|
88
|
-
```
|
|
49
|
+
Create a new file in `/plugins/MyProductListItemPlugin.tsx` with the following
|
|
50
|
+
contents:
|
|
89
51
|
|
|
90
|
-
|
|
52
|
+
```tsx
|
|
53
|
+
import type { ProductListItemProps } from '@graphcommerce/magento-product'
|
|
54
|
+
import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
|
|
55
|
+
import { Typography } from '@mui/material'
|
|
56
|
+
|
|
57
|
+
export const config: PluginConfig = {
|
|
58
|
+
type: 'component',
|
|
59
|
+
module: '@graphcommerce/magento-product',
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Exported name should be the same as the function you want to create a plugin for
|
|
63
|
+
export const ProductListItem = (props: PluginProps<ProductListItemProps>) => {
|
|
64
|
+
// Prev in this case is ProductListItem, you should be able to see this if you log it.
|
|
65
|
+
// Prev needs to be rendered and {...rest} always needs to be passed.
|
|
66
|
+
const { Prev, ...rest } = props
|
|
67
|
+
return (
|
|
68
|
+
<Prev
|
|
69
|
+
{...rest}
|
|
70
|
+
subTitle={
|
|
71
|
+
<Typography component='span' variant='caption'>
|
|
72
|
+
Plugin!
|
|
73
|
+
</Typography>
|
|
74
|
+
}
|
|
75
|
+
/>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## How do I write a function plugin?
|
|
81
|
+
|
|
82
|
+
Create a new file in `/plugins/myFunctionPlugin.tsx` with the following
|
|
83
|
+
contents:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import type { graphqlConfig as graphqlConfigType } from '@graphcommerce/graphql'
|
|
87
|
+
import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config'
|
|
88
|
+
import { createStoreLink } from '../link/createStoreLink'
|
|
89
|
+
|
|
90
|
+
export const config: PluginConfig = {
|
|
91
|
+
type: 'function',
|
|
92
|
+
module: '@graphcommerce/graphql',
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Exported name should be the same as the function you want to create a plugin for
|
|
96
|
+
export const graphqlConfig: FunctionPlugin<typeof graphqlConfigType> = (
|
|
97
|
+
prev,
|
|
98
|
+
conf,
|
|
99
|
+
) => {
|
|
100
|
+
const results = prev(conf)
|
|
101
|
+
return {
|
|
102
|
+
...results,
|
|
103
|
+
links: [...results.links, createStoreLink(conf.storefront.locale)],
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
91
107
|
|
|
92
|
-
|
|
93
|
-
file to load you plugin. To see what has happened, open the
|
|
94
|
-
`node_modules/@graphcommerce/magento-product/index.interceptor.tsx` and you
|
|
95
|
-
should see something like:
|
|
108
|
+
## How do I write a replacement plugin?
|
|
96
109
|
|
|
97
110
|
```tsx
|
|
98
|
-
|
|
99
|
-
import {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
function AwesomeProductListItemInterceptor(props: ProductListItemProps) {
|
|
111
|
-
return <AwesomeProductListItem {...props} Prev={ProductListItemBase} />
|
|
111
|
+
import { ProductCountProps } from '@graphcommerce/magento-product'
|
|
112
|
+
import { PluginConfig } from '@graphcommerce/next-config'
|
|
113
|
+
|
|
114
|
+
export const config: PluginConfig = {
|
|
115
|
+
type: 'replace',
|
|
116
|
+
module: '@graphcommerce/magento-product',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function ProductListCount(props: ProductCountProps) {
|
|
120
|
+
const { total_count } = props
|
|
121
|
+
return <div>{total_count}</div>
|
|
112
122
|
}
|
|
113
|
-
export const ProductListItem = AwesomeProductListItemInterceptor
|
|
114
123
|
```
|
|
115
124
|
|
|
116
|
-
|
|
125
|
+
Note: The original component can not be used, because we completely rewrite the
|
|
126
|
+
export. If you want to do this, a component or function plugin is a better
|
|
127
|
+
choice.
|
|
117
128
|
|
|
118
|
-
|
|
119
|
-
`AwesomeProductListItemInterceptor`
|
|
120
|
-
- `AwesomeProductListItemInterceptor` is a react component which renders
|
|
121
|
-
`AwesomeProductListItem` with a `Prev` prop.
|
|
122
|
-
- `AwesomeProductListItem` is the plugin you just created.
|
|
123
|
-
- `Prev` is the original `ProductListItem` (renamed to `ProductListItemBase`)
|
|
124
|
-
- `ProductListItemProps` are the props of the original `ProductListItem` and
|
|
125
|
-
thus your plugin is automatically validated by TypeScript.
|
|
129
|
+
## How do make sure my plugin is applied?
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
When creating the plugin for the first time you need to restart your dev server
|
|
132
|
+
once. After the first generation of the interceptor file, the file is watched
|
|
133
|
+
and changes will be picked up.
|
|
129
134
|
|
|
130
|
-
|
|
135
|
+
If everything went as expected you should see your plugin applied correct.
|
|
131
136
|
|
|
132
|
-
|
|
137
|
+
## How can I debug to see which plugins are applied?
|
|
138
|
+
|
|
139
|
+
You can enable debug mode in your graphcommerce.config.js:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
const config = {
|
|
143
|
+
debug: { pluginStatus: true },
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Or use `GC_DEBUG_PLUGIN_STATUS=true` in your environment variables.
|
|
133
148
|
|
|
134
149
|
### How are plugins loaded?
|
|
135
150
|
|
|
@@ -141,33 +156,66 @@ Package locations are the root and all packages with `graphcommerce` in the name
|
|
|
141
156
|
(This means all `@graphcommerce/*` packages and
|
|
142
157
|
`@your-company/graphcommerce-plugin-name`)
|
|
143
158
|
|
|
144
|
-
The Webpack plugin statically analyses the plugin
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
### Possible use cases
|
|
159
|
+
The Webpack plugin statically analyses the plugin files to find any valid
|
|
160
|
+
configuration. This is then used to create the interceptors.
|
|
148
161
|
|
|
149
|
-
|
|
150
|
-
work for other things such as:
|
|
162
|
+
### Conditionally include a plugin
|
|
151
163
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- Google recaptcha
|
|
155
|
-
- Compare functionality
|
|
156
|
-
- Wishlist functionality?
|
|
157
|
-
- Abstraction between GraphCommerce and Backends? (Magento, BigCommerce,
|
|
158
|
-
CommerceTools, etc.)
|
|
164
|
+
Provide an ifConfig in the plugin config to conditionally include a plugin if a
|
|
165
|
+
[configuration](./config.md) value is truthy:
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
```tsx
|
|
168
|
+
export const config: PluginConfig = {
|
|
169
|
+
type: 'component',
|
|
170
|
+
module: '@graphcommerce/magento-product',
|
|
171
|
+
ifConfig: 'demoMode',
|
|
172
|
+
}
|
|
173
|
+
```
|
|
161
174
|
|
|
162
|
-
|
|
163
|
-
[configuration](./config.md) value is truthy.
|
|
175
|
+
Or checking on a value:
|
|
164
176
|
|
|
165
177
|
```tsx
|
|
166
|
-
|
|
167
|
-
|
|
178
|
+
export const config: PluginConfig<'compareVariant'> = {
|
|
179
|
+
type: 'component',
|
|
180
|
+
module: '@graphcommerce/magento-product',
|
|
181
|
+
ifConfig: ['compareVariant', 'CHECKBOX'],
|
|
182
|
+
}
|
|
168
183
|
```
|
|
169
184
|
|
|
170
185
|
### Plugin loading order
|
|
171
186
|
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
The plugin loading order is determined by the order of the dependencies defined
|
|
188
|
+
in the package.json. If the order isn't correct, make sure you've defined the
|
|
189
|
+
correct dependencies in your package.json.
|
|
190
|
+
|
|
191
|
+
Local plugins are closest to the original component, meaning that package
|
|
192
|
+
specific plugins have already been called before your plugin is called.
|
|
193
|
+
|
|
194
|
+
## How does it work?
|
|
195
|
+
|
|
196
|
+
After the creation of the plugin file GraphCommerce will create an 'interceptor'
|
|
197
|
+
for your file.
|
|
198
|
+
|
|
199
|
+
To see the the created plugin for ProductListItem, '_Go to Definition_'
|
|
200
|
+
(CMD/Ctrl+Click) on `<ProductListItem>` in
|
|
201
|
+
`components/ProductListItems/productListRenderer.tsx`. You should now go to the
|
|
202
|
+
`ProductListItem.interceptor.tsx` file.
|
|
203
|
+
|
|
204
|
+
In this file the original `ProductListItem` is replaced with
|
|
205
|
+
`PluginDemoProductListItemInterceptor`. The interceptor renders
|
|
206
|
+
`<PluginDemoProductListItemSource />` with a `Prev` prop which is the plugin.
|
|
207
|
+
|
|
208
|
+
The whole plugin 'chain' is constructed here and eventually ending up on
|
|
209
|
+
`ProductListItemOriginal` which is the original component (but renamed).
|
|
210
|
+
|
|
211
|
+
### Examples
|
|
212
|
+
|
|
213
|
+
In the examples above we've extended the product list items, but it should also
|
|
214
|
+
work for other things such as:
|
|
215
|
+
|
|
216
|
+
- [Update the gallery when a configurable is selected](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/magento-product-configurable/plugins/ConfigurableProductPage/ConfigurableProductPageGallery.tsx)
|
|
217
|
+
- [Insert the Google Recaptcha Script](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/googlerecaptcha/plugins/GrecaptchaGraphQLProvider.tsx)
|
|
218
|
+
- [Activate Google Recaptcha when a form is loaded](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/googlerecaptcha/plugins/GrecaptchaApolloErrorSnackbar.tsx)
|
|
219
|
+
- [Add a compare icon next to the cart icon](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/magento-compare/plugins/AddCompareFabNextToCart.tsx)
|
|
220
|
+
- [Add a compare icon to the ProductListItem](https://github.com/graphcommerce-org/graphcommerce/blob/canary/packages/magento-compare/plugins/CompareAbleProductListItem.tsx)
|
|
221
|
+
- etc.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Multiple themes/brands with multiple websites
|
|
2
|
+
|
|
3
|
+
When deciding how to develop multiple themes/brands, there are several
|
|
4
|
+
gradations of customizability.
|
|
5
|
+
|
|
6
|
+
Deciding on how to approach this is a trade-off between the amount of
|
|
7
|
+
customizability and the amount of code duplication.
|
|
8
|
+
|
|
9
|
+
## Gradations of modularization/thematization
|
|
10
|
+
|
|
11
|
+
### Level 1: One codebase, one build. Differences are configured in GraphCommerceStorefrontConfig
|
|
12
|
+
|
|
13
|
+
- Advantage: Simple, everything is easy to configure in the config.
|
|
14
|
+
- Advantage: Upgrade once
|
|
15
|
+
- Disadvantage: Not tree shakable (very large differences between brands can
|
|
16
|
+
become problematic)
|
|
17
|
+
|
|
18
|
+
This requires discipline from the developer that we maintain the 'Single
|
|
19
|
+
responsibility' principle for components. Components that actually serve two
|
|
20
|
+
completely separate functionalities depending on the brand are not desirable.
|
|
21
|
+
|
|
22
|
+
Create a Config.graphqls in your graphql directory with the following contents:
|
|
23
|
+
|
|
24
|
+
```graphql
|
|
25
|
+
enum ThemeName {
|
|
26
|
+
BRAND_1
|
|
27
|
+
BRAND_2
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
extend input GraphCommerceStorefrontConfig {
|
|
31
|
+
themeName: ThemeName!
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Applying a different theme based on the store configuration:
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
// in _app.tsx
|
|
39
|
+
const { themeName } = useStorefrontConfig()
|
|
40
|
+
const theme = useMemo(() => {
|
|
41
|
+
if (themeName === 'BRAND_1') {
|
|
42
|
+
const brand1Palette = ...
|
|
43
|
+
return createThemeWithPalette(brand1Palette)
|
|
44
|
+
}
|
|
45
|
+
}, [domain])
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Applying a different component based on the store configuration:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
export function MyComponent() {
|
|
52
|
+
const { themeName } = useStorefrontConfig()
|
|
53
|
+
|
|
54
|
+
if (themeName === 'BRAND_1') return <Brand1Component>
|
|
55
|
+
return <Brand2Component {...}/>
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Level 2: One codebase, multiple builds. Differences are configured in GraphCommerceConfig
|
|
60
|
+
|
|
61
|
+
- Advantage: Tree shakable
|
|
62
|
+
- Advantage: Upgrade once
|
|
63
|
+
- Disadvantage: Multiple builds
|
|
64
|
+
- Disadvantage: Multiple deployments
|
|
65
|
+
|
|
66
|
+
Create a Config.graphqls in your graphql directory with the following contents:
|
|
67
|
+
|
|
68
|
+
```graphql
|
|
69
|
+
enum ThemeName {
|
|
70
|
+
BRAND_1
|
|
71
|
+
BRAND_2
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
extend input GraphCommerceConfig {
|
|
75
|
+
themeName: ThemeName!
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
During deploy you'd have to set the theme that is being build:
|
|
80
|
+
`GC_THEME_NAME=BRAND_1`.
|
|
81
|
+
|
|
82
|
+
Create a separate theme for each brand:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
let theme: Theme
|
|
86
|
+
if (import.meta.graphCommerce.theme === 'BRAND_1') {
|
|
87
|
+
const brand1Palette = ...
|
|
88
|
+
theme = createThemeWithPalette(brand1Palette)
|
|
89
|
+
} else if (import.meta.graphCommerce.theme === 'BRAND_2') {
|
|
90
|
+
const brand2Palette = ...
|
|
91
|
+
theme = createThemeWithPalette(brand2Palette)
|
|
92
|
+
}
|
|
93
|
+
theme.components = createOverrides(theme) as Components
|
|
94
|
+
|
|
95
|
+
export { theme }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Replace/Plugin a component based on the theme:
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
// plugins/BRAND_1/magento-product/Replace.tsx
|
|
102
|
+
export const config: PluginConfig<'themeName'> = {
|
|
103
|
+
type: 'replace',
|
|
104
|
+
module: '@graphcommerce/magento-product',
|
|
105
|
+
ifConfig: ['themeName', 'BRAND_1'],
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function ProductListItem(props: ProductListItemProps) {
|
|
109
|
+
//...
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Now when a new brand is added you can copy-paste the BRAND_1 directory and you
|
|
114
|
+
should be able to modify the components to your liking.
|
|
115
|
+
|
|
116
|
+
<!--
|
|
117
|
+
### Level 3: Monorepo with one graphcommerce instance, but a separate generic package per brand.
|
|
118
|
+
|
|
119
|
+
- Advantage: Tree shakable
|
|
120
|
+
- Advantage: Full flexibility
|
|
121
|
+
- Disadvantage: Files are copied per brand.
|
|
122
|
+
- Disadvantage: Upgrades are duplicated
|
|
123
|
+
- Disadvantage: Projects diverge quickly and become hard to maintain.
|
|
124
|
+
|
|
125
|
+
This requires you to modify all imports of the examples directory, thus making
|
|
126
|
+
upgrades more difficult. GraphCommerce does not offer a flexible solution for
|
|
127
|
+
this.
|
|
128
|
+
|
|
129
|
+
To achieve this we could: Offer a way to also handle `export * from 'my-brand'`
|
|
130
|
+
in plugins. -->
|
package/package.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"name": "@graphcommerce/docs",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/docs",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce/docs",
|
|
5
|
-
"version": "8.1.0-canary.
|
|
5
|
+
"version": "8.1.0-canary.5",
|
|
6
6
|
"sideEffects": true,
|
|
7
7
|
"peerDependencies": {
|
|
8
|
-
"@graphcommerce/prettier-config-pwa": "^8.1.0-canary.
|
|
8
|
+
"@graphcommerce/prettier-config-pwa": "^8.1.0-canary.5"
|
|
9
9
|
},
|
|
10
10
|
"prettier": "@graphcommerce/prettier-config-pwa"
|
|
11
11
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Upgrading from GraphCommerce 7 to 8
|
|
2
|
+
|
|
3
|
+
Depending on the amounts of customisations you've made, there are some manual
|
|
4
|
+
steps. Please follow the regular [upgrade steps first](./readme.md).
|
|
5
|
+
|
|
6
|
+
1. ReactPlugin TypeScript definition is removed.
|
|
7
|
+
|
|
8
|
+
## 1. ReactPlugin TypeScript definition is removed
|
|
9
|
+
|
|
10
|
+
The `ReactPlugin` TypeScript definition has been removed and only `PluginProps`
|
|
11
|
+
is available.
|
|
12
|
+
|
|
13
|
+
Replace
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
const MyPlugin: ReactPlugin<typeof OriginalComponent> = (props) => {
|
|
17
|
+
const { Prev, ...rest } = props
|
|
18
|
+
return <Prev {...rest} />
|
|
19
|
+
}
|
|
20
|
+
export const Plugin = MyPlugin
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Now becomes:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
const MyPlugin = (props: PluginProps<OriginalComponentProps>) => {
|
|
27
|
+
const { Prev, ...rest } = props
|
|
28
|
+
return <Prev {...rest} />
|
|
29
|
+
}
|
|
30
|
+
export const Plugin = MyPlugin
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
There is a new plugin configuration method by using
|
|
34
|
+
`export config: PluginConfig = {}`.
|