@graphcommerce/docs 6.0.0-canary.45 → 6.0.0-canary.47
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 +4 -0
- package/feature-list.md +1 -1
- package/framework/plugins-react.md +93 -136
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
package/feature-list.md
CHANGED
|
@@ -39,7 +39,7 @@ Features taken from the Magento Commerce 2 Feature List
|
|
|
39
39
|
store data. — [Commerce]
|
|
40
40
|
- [x] Offer free shipping and percent, fixed amount, and buy X get Y free
|
|
41
41
|
discounts. — [Commerce]
|
|
42
|
-
- [
|
|
42
|
+
- [x] Set multi-tier pricing for quantity discounts.
|
|
43
43
|
- [ ] Get minimum advertised price (MAP) support. — [Todo]
|
|
44
44
|
|
|
45
45
|
### Search engine optimization
|
|
@@ -1,160 +1,121 @@
|
|
|
1
1
|
# Plugins React
|
|
2
2
|
|
|
3
|
-
GraphCommerce's React plugin system allows you to extend GraphCommerce
|
|
4
|
-
|
|
5
|
-
right places.
|
|
3
|
+
GraphCommerce's React plugin system allows you to extend GraphCommerce's build
|
|
4
|
+
in components with your own logic.
|
|
6
5
|
|
|
7
|
-
- Plug-and-play: It is be possible to install packages after which they
|
|
8
|
-
immediately work.
|
|
9
6
|
- No runtime overhead: The plugin system is fully implemented in webpack and
|
|
10
7
|
- Easy plugin creation: Configuration should happen in the plugin file, not a
|
|
11
8
|
separate configuration file.
|
|
9
|
+
- Should be validated with TypeScript
|
|
12
10
|
|
|
13
|
-
## What
|
|
14
|
-
|
|
15
|
-
Without plugins the only way to add new functionality is by modifying the code
|
|
16
|
-
of your project at multiple places. We often pass props to components to
|
|
17
|
-
customize them, but sometimes we also place hooks at multiple places.
|
|
18
|
-
|
|
19
|
-
For example, to add a new payment method it was necessary to modify the props of
|
|
20
|
-
`<PaymentMethodContextProvider methods={[...braintree]}>`
|
|
21
|
-
|
|
22
|
-
This causes problems:
|
|
23
|
-
|
|
24
|
-
- Upgrades: If GraphCommerce changes something somewhere in the code where you
|
|
25
|
-
have already modified the code, you get an upgrade conflict which you have to
|
|
26
|
-
manually resolve. By using plugins you can avoid this.
|
|
27
|
-
- New packages: When you install a complex new package, it can happen that you
|
|
28
|
-
have to modify the code of your project at multiple places. This is not
|
|
29
|
-
necessary with plugins.
|
|
30
|
-
|
|
31
|
-
## What is a plugin?
|
|
11
|
+
## What is a plugin
|
|
32
12
|
|
|
33
13
|
A plugin is a way to modify React Components by wrapping them, without having to
|
|
34
|
-
modify the code
|
|
14
|
+
modify the code directly.
|
|
35
15
|
|
|
36
16
|
For the M2 people: Think of around plugins, but without configuration files and
|
|
37
17
|
no performance penalty.
|
|
38
18
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
19
|
+
## How do I write a plugin?
|
|
20
|
+
|
|
21
|
+
In this example we're going to add a 'BY GC' text to list items, as can seen on
|
|
22
|
+
the demo on
|
|
23
|
+
[category pages](https://graphcommerce.vercel.app/nl/women/business).
|
|
24
|
+
|
|
25
|
+
1. Create a new file in `/plugins/ProductListItemByGC.tsx` with the following
|
|
26
|
+
contents:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import type { ProductListItemProps } from '@graphcommerce/magento-product'
|
|
30
|
+
import type { PluginProps } from '@graphcommerce/next-config'
|
|
31
|
+
import { Typography } from '@mui/material'
|
|
32
|
+
|
|
33
|
+
export const component = 'ProductListItem' // Component to extend, required
|
|
34
|
+
export const exported = '@graphcommerce/magento-product' // Location where the component is exported, required
|
|
35
|
+
|
|
36
|
+
function AwesomeProductListItem(props: PluginProps<ProductListItemProps>) {
|
|
37
|
+
// Prev in this case is ProductListItem, you should be able to see this if you log it.
|
|
38
|
+
const { Prev, ...rest } = props
|
|
39
|
+
return (
|
|
40
|
+
<Prev
|
|
41
|
+
{...rest}
|
|
42
|
+
subTitle={
|
|
43
|
+
<Typography component='span' variant='caption'>
|
|
44
|
+
Plugin!
|
|
45
|
+
</Typography>
|
|
46
|
+
}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
export const Plugin = AwesomeProductListItem // An export with the name Plugin, required
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. Trigger the 'interceptor generation' so GraphCommerce knows of the existence
|
|
54
|
+
of your plugin. To enable: Modify the page that you expect the plugin to
|
|
55
|
+
occur on. In this case modify `pages/[...url].tsx` by adding a few linebreaks
|
|
56
|
+
and save the file
|
|
57
|
+
|
|
58
|
+
If everything went as expected you should see `Plugin!` below the product
|
|
59
|
+
name.
|
|
60
|
+
|
|
61
|
+
3. Happy programming!
|
|
62
|
+
|
|
63
|
+
## How does it work?
|
|
64
|
+
|
|
65
|
+
After the creation of the plugin file GraphCommerce will create an interceptor
|
|
66
|
+
file to load you plugin. To see what has happened, open the
|
|
67
|
+
`node_modules/@graphcommerce/magento-product/index.interceptor.tsx` and you
|
|
68
|
+
should see something like:
|
|
62
69
|
|
|
63
70
|
```tsx
|
|
64
|
-
|
|
65
|
-
import
|
|
66
|
-
import {
|
|
67
|
-
|
|
68
|
-
// Component to extend, required
|
|
69
|
-
export const component = 'PaymentMethodContextProvider'
|
|
71
|
+
export * from '.'
|
|
72
|
+
import { Plugin as AwesomeProductListItem } from '../../examples/magento-graphcms/plugins/AwesomeProductListItem'
|
|
73
|
+
import { ComponentProps } from 'react'
|
|
74
|
+
import { ProductListItem as ProductListItemBase } from '.'
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Interceptor for `<ProductListItem/>` with these plugins:
|
|
78
|
+
*
|
|
79
|
+
* - `../../examples/magento-graphcms/plugins/AwesomeProductListItem`
|
|
80
|
+
*/
|
|
81
|
+
type ProductListItemProps = ComponentProps<typeof ProductListItemBase>
|
|
73
82
|
|
|
74
|
-
function
|
|
75
|
-
props
|
|
76
|
-
) {
|
|
77
|
-
const { Prev, modules, ...rest } = props
|
|
78
|
-
return <Prev {...rest} modules={{ ...modules, purchaseorder }} />
|
|
83
|
+
function AwesomeProductListItemInterceptor(props: ProductListItemProps) {
|
|
84
|
+
return <AwesomeProductListItem {...props} Prev={ProductListItemBase} />
|
|
79
85
|
}
|
|
80
|
-
|
|
81
|
-
/** The export must be named `Plugin` and must accept a Prev component to render */
|
|
82
|
-
export const Plugin = AddIncludedMethods
|
|
86
|
+
export const ProductListItem = AwesomeProductListItemInterceptor
|
|
83
87
|
```
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
If you read the interceptor file from the bottom up, you see:
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
existing component
|
|
91
|
+
- The original `ProductListItem` is replaced with
|
|
92
|
+
`AwesomeProductListItemInterceptor`
|
|
93
|
+
- `AwesomeProductListItemInterceptor` is a react component which renders
|
|
94
|
+
`AwesomeProductListItem` with a `Prev` prop.
|
|
95
|
+
- `AwesomeProductListItem` is the plugin you just created.
|
|
96
|
+
- `Prev` is the original `ProductListItem` (renamed to `ProductListItemBase`)
|
|
97
|
+
- `ProductListItemProps` are the props of the original `ProductListItem` and
|
|
98
|
+
thus your plugin is automatically validated by TypeScript.
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
So in conclusion, a plugin is a react component that renders the original
|
|
101
|
+
component with a `Prev` prop. The `Prev` prop is the original component.
|
|
98
102
|
|
|
99
|
-
|
|
100
|
-
/* This file is automatically generated for @graphcommerce/magento-cart-payment-method */
|
|
103
|
+
When opening the React debugger you can see the plugin wrapped.
|
|
101
104
|
|
|
102
|
-
|
|
103
|
-
import { Plugin as GaPaymentMethodButton } from '@graphcommerce/googleanalytics/plugins/GaPaymentMethodButton'
|
|
104
|
-
import { Plugin as GaPaymentMethodContextProvider } from '@graphcommerce/googleanalytics/plugins/GaPaymentMethodContextProvider'
|
|
105
|
-
import { Plugin as AddIncludedMethods } from '@graphcommerce/magento-payment-included/plugins/AddIncludedMethods'
|
|
106
|
-
import { ComponentProps } from 'react'
|
|
107
|
-
import {
|
|
108
|
-
PaymentMethodButton as PaymentMethodButtonBase,
|
|
109
|
-
PaymentMethodContextProvider as PaymentMethodContextProviderBase,
|
|
110
|
-
} from '.'
|
|
105
|
+
<img width="263" alt="Schermafbeelding 2023-03-15 om 12 16 59" src="https://user-images.githubusercontent.com/1244416/225293707-1ce1cd87-108b-4f28-b9ee-0c5d68d9a886.png">
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
* Interceptor for `<PaymentMethodButton/>` with these plugins:
|
|
114
|
-
*
|
|
115
|
-
* - `@graphcommerce/googleanalytics/plugins/GaPaymentMethodButton`
|
|
116
|
-
*/
|
|
117
|
-
type PaymentMethodButtonProps = ComponentProps<typeof PaymentMethodButtonBase>
|
|
107
|
+
### How are plugins loaded?
|
|
118
108
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
export const PaymentMethodButton = GaPaymentMethodButtonInterceptor
|
|
109
|
+
GraphCommerce uses a custom Webpack plugin to load the plugins. The plugin does
|
|
110
|
+
a glob search for plugin folders in each GraphCommerce related pacakge:
|
|
111
|
+
`${packageLocation}/plugins/**/*.tsx`
|
|
123
112
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
* - `@graphcommerce/magento-payment-included/plugins/AddIncludedMethods`
|
|
128
|
-
* - `@graphcommerce/googleanalytics/plugins/GaPaymentMethodContextProvider`
|
|
129
|
-
*/
|
|
130
|
-
type PaymentMethodContextProviderProps = ComponentProps<
|
|
131
|
-
typeof PaymentMethodContextProviderBase
|
|
132
|
-
>
|
|
133
|
-
|
|
134
|
-
function AddIncludedMethodsInterceptor(
|
|
135
|
-
props: PaymentMethodContextProviderProps,
|
|
136
|
-
) {
|
|
137
|
-
return (
|
|
138
|
-
<AddIncludedMethods {...props} Prev={PaymentMethodContextProviderBase} />
|
|
139
|
-
)
|
|
140
|
-
}
|
|
141
|
-
function GaPaymentMethodContextProviderInterceptor(
|
|
142
|
-
props: PaymentMethodContextProviderProps,
|
|
143
|
-
) {
|
|
144
|
-
return (
|
|
145
|
-
<GaPaymentMethodContextProvider
|
|
146
|
-
{...props}
|
|
147
|
-
Prev={AddIncludedMethodsInterceptor}
|
|
148
|
-
/>
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
export const PaymentMethodContextProvider =
|
|
152
|
-
GaPaymentMethodContextProviderInterceptor
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
React profile will show that all components are nested:
|
|
113
|
+
Package locations are the root and all packages with `graphcommerce` in the name
|
|
114
|
+
(This means all `@graphcommerce/*` packages and
|
|
115
|
+
`@your-company/graphcommerce-plugin-name`)
|
|
156
116
|
|
|
157
|
-
|
|
117
|
+
The Webpack plugin statically analyses the plugin file to find `component`,
|
|
118
|
+
`exported` and `ifConfig` and extracts that information.
|
|
158
119
|
|
|
159
120
|
### Possible use cases
|
|
160
121
|
|
|
@@ -172,17 +133,13 @@ work for other things such as:
|
|
|
172
133
|
### Conditionally include a plugin
|
|
173
134
|
|
|
174
135
|
Provide an ifConfig export in the plugin that will only include the plugin if a
|
|
175
|
-
configuration value is truety.
|
|
136
|
+
[configuration](./config.md) value is truety.
|
|
176
137
|
|
|
177
138
|
```tsx
|
|
178
|
-
|
|
139
|
+
import type { IfConfig } from '@graphcommerce/next-config'
|
|
140
|
+
export const ifConfig: IfConfig = 'googleAnalytics'
|
|
179
141
|
```
|
|
180
142
|
|
|
181
|
-
### When to use a plugin?
|
|
182
|
-
|
|
183
|
-
A plugin should be used when a new package is created that influences the
|
|
184
|
-
behavior of other packages.
|
|
185
|
-
|
|
186
143
|
### Plugin loading order
|
|
187
144
|
|
|
188
145
|
A plugin is injected later than the dependencies of the package. So if a plugin
|
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": "6.0.0-canary.
|
|
5
|
+
"version": "6.0.0-canary.47",
|
|
6
6
|
"sideEffects": true,
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"@graphcommerce/prettier-config-pwa": "6.0.0-canary.
|
|
8
|
+
"@graphcommerce/prettier-config-pwa": "6.0.0-canary.47"
|
|
9
9
|
},
|
|
10
10
|
"prettier": "@graphcommerce/prettier-config-pwa"
|
|
11
11
|
}
|