eddev 0.2.28 → 0.2.31

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.
Files changed (92) hide show
  1. package/build/get-webpack-config.js +1 -0
  2. package/gravityforms/useGravityForm.js +13 -3
  3. package/package.json +6 -5
  4. package/serverless-template/tsconfig.json +1 -0
  5. package/style/createStitches.js +10 -3
  6. package/docs_old/README.md +0 -33
  7. package/docs_old/babel.config.js +0 -3
  8. package/docs_old/blog/2019-05-28-first-blog-post.md +0 -12
  9. package/docs_old/blog/2019-05-29-long-blog-post.md +0 -44
  10. package/docs_old/blog/2021-08-01-mdx-blog-post.mdx +0 -20
  11. package/docs_old/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  12. package/docs_old/blog/2021-08-26-welcome/index.md +0 -25
  13. package/docs_old/blog/authors.yml +0 -17
  14. package/docs_old/docs/graphql/1.graphql-overview.md +0 -62
  15. package/docs_old/docs/graphql/2.query-hooks.md +0 -238
  16. package/docs_old/docs/graphql/3.extending-wpgraphql.md +0 -3
  17. package/docs_old/docs/graphql/_category_.json +0 -4
  18. package/docs_old/docs/graphql/img/graphql-ide.png +0 -0
  19. package/docs_old/docs/graphql/img/infinite-example.gif +0 -0
  20. package/docs_old/docs/graphql/img/mutation-example.gif +0 -0
  21. package/docs_old/docs/gutenberg/1.overview.md +0 -25
  22. package/docs_old/docs/gutenberg/2.block-definition.md +0 -37
  23. package/docs_old/docs/gutenberg/3.block-acf.md +0 -13
  24. package/docs_old/docs/gutenberg/4.block-graphql.md +0 -63
  25. package/docs_old/docs/gutenberg/5.inline-editing.md +0 -33
  26. package/docs_old/docs/gutenberg/6.nested-blocks.md +0 -80
  27. package/docs_old/docs/gutenberg/7.restricting-to-post-types.md +0 -38
  28. package/docs_old/docs/gutenberg/8.restricting-to-page-templates.md +0 -26
  29. package/docs_old/docs/gutenberg/9.dynamic-blocks.md +0 -21
  30. package/docs_old/docs/gutenberg/_category_.json +0 -4
  31. package/docs_old/docs/gutenberg/img/create-acf-fields-for-block.png +0 -0
  32. package/docs_old/docs/gutenberg/img/example-acf-single-project-tile.png +0 -0
  33. package/docs_old/docs/how-to/1.new-site.md +0 -36
  34. package/docs_old/docs/how-to/2.deployment.md +0 -31
  35. package/docs_old/docs/how-to/3.menus.md +0 -72
  36. package/docs_old/docs/how-to/4.options-pages.md +0 -41
  37. package/docs_old/docs/how-to/5.bundle-size.md +0 -177
  38. package/docs_old/docs/how-to/6.favicons.md +0 -82
  39. package/docs_old/docs/how-to/_category_.json +0 -4
  40. package/docs_old/docs/how-to/img/bundle-analysis-after.png +0 -0
  41. package/docs_old/docs/how-to/img/bundle-analysis-before.png +0 -0
  42. package/docs_old/docs/how-to/img/bundle-webpack-after.png +0 -0
  43. package/docs_old/docs/how-to/img/bundle-webpack-before.png +0 -0
  44. package/docs_old/docs/how-to/img/favicon-codebase.png +0 -0
  45. package/docs_old/docs/how-to/img/favicon-figma-export.png +0 -0
  46. package/docs_old/docs/how-to/img/favicon-figma.png +0 -0
  47. package/docs_old/docs/intro.md +0 -7
  48. package/docs_old/docs/known-issues.md +0 -8
  49. package/docs_old/docs/serverless/1.overview.md +0 -1
  50. package/docs_old/docs/serverless/2.config.md +0 -1
  51. package/docs_old/docs/serverless/3.wordpress-vercel.md +0 -8
  52. package/docs_old/docs/serverless/4.apis.md +0 -1
  53. package/docs_old/docs/serverless/5.rpc.md +0 -1
  54. package/docs_old/docs/serverless/_category_.json +0 -4
  55. package/docs_old/docs/stack/1-WordPress.md +0 -18
  56. package/docs_old/docs/stack/2-Flywheel.md +0 -15
  57. package/docs_old/docs/stack/3-React.md +0 -12
  58. package/docs_old/docs/stack/4-TypeScript.md +0 -13
  59. package/docs_old/docs/stack/5-WPGraphQL.md +0 -21
  60. package/docs_old/docs/stack/6-eddev.md +0 -9
  61. package/docs_old/docs/stack/_category_.json +0 -4
  62. package/docs_old/docs/tooling/1.scripts.md +0 -25
  63. package/docs_old/docs/tooling/2.aliases.md +0 -13
  64. package/docs_old/docs/tooling/3.defines.md +0 -13
  65. package/docs_old/docs/tooling/4.config-file.md +0 -14
  66. package/docs_old/docs/tooling/_category_.json +0 -4
  67. package/docs_old/docs/views/1.overview.md +0 -31
  68. package/docs_old/docs/views/2.queries.md +0 -18
  69. package/docs_old/docs/views/3.content-blocks.md +0 -36
  70. package/docs_old/docs/views/4.app-view.md +0 -35
  71. package/docs_old/docs/views/5.page-templates.md +0 -20
  72. package/docs_old/docs/views/_category_.json +0 -4
  73. package/docs_old/docusaurus.config.js +0 -119
  74. package/docs_old/package.json +0 -40
  75. package/docs_old/sidebars.js +0 -26
  76. package/docs_old/src/components/HomepageFeatures.js +0 -64
  77. package/docs_old/src/components/HomepageFeatures.module.css +0 -11
  78. package/docs_old/src/css/custom.css +0 -28
  79. package/docs_old/src/pages/index.js +0 -36
  80. package/docs_old/src/pages/index.module.css +0 -23
  81. package/docs_old/src/pages/markdown-page.md +0 -7
  82. package/docs_old/static/.nojekyll +0 -0
  83. package/docs_old/static/img/docusaurus.png +0 -0
  84. package/docs_old/static/img/favicon.ico +0 -0
  85. package/docs_old/static/img/logo-black.svg +0 -4
  86. package/docs_old/static/img/logo-white.svg +0 -4
  87. package/docs_old/static/img/tutorial/docsVersionDropdown.png +0 -0
  88. package/docs_old/static/img/tutorial/localeDropdown.png +0 -0
  89. package/docs_old/static/img/undraw_docusaurus_mountain.svg +0 -170
  90. package/docs_old/static/img/undraw_docusaurus_react.svg +0 -169
  91. package/docs_old/static/img/undraw_docusaurus_tree.svg +0 -1
  92. package/docs_old/yarn.lock +0 -8814
@@ -130,6 +130,7 @@ function getWebpackConfig(opts) {
130
130
  ALIAS["@components"] = path_1.default.join(opts.baseDirectory, "components");
131
131
  ALIAS["@views"] = path_1.default.join(opts.baseDirectory, "views");
132
132
  ALIAS["@hooks"] = path_1.default.join(opts.baseDirectory, "hooks");
133
+ ALIAS["@lib"] = path_1.default.join(opts.baseDirectory, "lib");
133
134
  ALIAS["@queries"] = path_1.default.join(opts.baseDirectory, "hooks/queries");
134
135
  ALIAS["@utils"] = path_1.default.join(opts.baseDirectory, "utils");
135
136
  RULES.push({
@@ -122,14 +122,24 @@ function useGravityForm(opts) {
122
122
  }
123
123
  exports.useGravityForm = useGravityForm;
124
124
  function prepareValuesPayload(form, state, data) {
125
- for (var _i = 0, _a = form.fields; _i < _a.length; _i++) {
126
- var field = _a[_i];
125
+ var _loop_1 = function (field) {
127
126
  var value = state.values[field.id];
128
127
  var key = "input_" + field.id;
129
128
  if (field.type === "consent") {
130
129
  key += "_1";
131
130
  }
132
- data[key] = value;
131
+ if (field.type === "checkbox") {
132
+ field.choices.forEach(function (choice, i) {
133
+ data["".concat(key, ".").concat(i + 1)] = (value === null || value === void 0 ? void 0 : value.includes(choice.value)) ? choice.value : null;
134
+ });
135
+ }
136
+ else {
137
+ data[key] = value;
138
+ }
139
+ };
140
+ for (var _i = 0, _a = form.fields; _i < _a.length; _i++) {
141
+ var field = _a[_i];
142
+ _loop_1(field);
133
143
  }
134
144
  return data;
135
145
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eddev",
3
- "version": "0.2.28",
3
+ "version": "0.2.31",
4
4
  "main": "./index.js",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -21,14 +21,15 @@
21
21
  "@types/loadable__component": "^5.13.4",
22
22
  "@types/node": "^16.7.10",
23
23
  "@types/react": "^17.0.36",
24
- "@types/react-dom": "^17.0.11",
24
+ "@types/react-dom": "^18.0.6",
25
25
  "@types/react-inspector": "^4.0.2",
26
26
  "@types/rimraf": "^3.0.2",
27
27
  "@types/url-parse": "^1.4.4",
28
28
  "@types/webpack-dev-server": "^3.11.2",
29
29
  "csstype": "^3.0.9",
30
30
  "next": "^12.1.6",
31
- "react-html-props": "^1.0.32"
31
+ "react-html-props": "^1.0.32",
32
+ "react-use": "^17.4.0"
32
33
  },
33
34
  "dependencies": {
34
35
  "@babel/core": "^7.15.5",
@@ -89,9 +90,9 @@
89
90
  "to-icon": "^1.1.4",
90
91
  "typescript": "4.5.5",
91
92
  "url-parse": "^1.5.3",
92
- "webpack": "^5.52.0",
93
+ "webpack": "5.74.0",
93
94
  "webpack-bundle-analyzer": "^4.5.0",
94
- "webpack-dev-server": "^3.11.2",
95
+ "webpack-dev-server": "3.11.3",
95
96
  "webpack-hot-middleware": "^2.25.0",
96
97
  "webpack-virtual-modules": "^0.4.3",
97
98
  "zod": "^3.11.6",
@@ -21,6 +21,7 @@
21
21
  "@components/*": ["components/*"],
22
22
  "@views/*": ["views/*"],
23
23
  "@hooks/*": ["hooks/*"],
24
+ "@lib/*": ["lib/*"],
24
25
  "@utils/*": ["utils/*"],
25
26
  "@queries/*": ["hooks/queries/*"],
26
27
  "@theme": ["theme.css.tsx"],
@@ -274,12 +274,13 @@ function parseResponsiveObject(breakpoints, object) {
274
274
  }
275
275
  exports.parseResponsiveObject = parseResponsiveObject;
276
276
  function getResponsiveObjectStyles(breakpoints, object, varName, unit) {
277
- var _a, _b;
278
- var _c;
277
+ var _a, _b, _c;
278
+ var _d;
279
279
  if (unit === void 0) { unit = "px"; }
280
280
  // Prescale object
281
281
  object = __assign({}, object);
282
282
  var parsed = parseResponsiveObject(breakpoints, object);
283
+ console.log("PARSED", parsed);
283
284
  var globals = {};
284
285
  for (var _i = 0, parsed_1 = parsed; _i < parsed_1.length; _i++) {
285
286
  var atom = parsed_1[_i];
@@ -294,8 +295,14 @@ function getResponsiveObjectStyles(breakpoints, object, varName, unit) {
294
295
  _b[varName] = atom.concreteValue + unit,
295
296
  _b);
296
297
  }
298
+ else if (atom.defined) {
299
+ globals["@" + atom.breakpoint] = (_c = {},
300
+ _c[varName] = atom.value,
301
+ _c);
302
+ }
297
303
  }
298
- return [globals, (_c = globals["@initial"]) === null || _c === void 0 ? void 0 : _c[varName]];
304
+ console.log("GLOBALS", globals);
305
+ return [globals, (_d = globals["@initial"]) === null || _d === void 0 ? void 0 : _d[varName]];
299
306
  }
300
307
  exports.getResponsiveObjectStyles = getResponsiveObjectStyles;
301
308
  // parseResponsiveTokens({'@initial': blah, '@desktop': blah}, breakpoints, )
@@ -1,33 +0,0 @@
1
- # Website
2
-
3
- This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
4
-
5
- ### Installation
6
-
7
- ```
8
- $ yarn
9
- ```
10
-
11
- ### Local Development
12
-
13
- ```
14
- $ yarn start
15
- ```
16
-
17
- This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
18
-
19
- ### Build
20
-
21
- ```
22
- $ yarn build
23
- ```
24
-
25
- This command generates static content into the `build` directory and can be served using any static contents hosting service.
26
-
27
- ### Deployment
28
-
29
- ```
30
- $ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
31
- ```
32
-
33
- If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3
- };
@@ -1,12 +0,0 @@
1
- ---
2
- slug: first-blog-post
3
- title: First Blog Post
4
- authors:
5
- name: Gao Wei
6
- title: Docusaurus Core Team
7
- url: https://github.com/wgao19
8
- image_url: https://github.com/wgao19.png
9
- tags: [hola, docusaurus]
10
- ---
11
-
12
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
@@ -1,44 +0,0 @@
1
- ---
2
- slug: long-blog-post
3
- title: Long Blog Post
4
- authors: endi
5
- tags: [hello, docusaurus]
6
- ---
7
-
8
- This is the summary of a very long blog post,
9
-
10
- Use a `<!--` `truncate` `-->` comment to limit blog post size in the list view.
11
-
12
- <!--truncate-->
13
-
14
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
15
-
16
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
17
-
18
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
19
-
20
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
21
-
22
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
23
-
24
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
25
-
26
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
27
-
28
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
29
-
30
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
31
-
32
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
33
-
34
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
35
-
36
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
37
-
38
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
39
-
40
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
41
-
42
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
43
-
44
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
@@ -1,20 +0,0 @@
1
- ---
2
- slug: mdx-blog-post
3
- title: MDX Blog Post
4
- authors: [slorber]
5
- tags: [docusaurus]
6
- ---
7
-
8
- Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
9
-
10
- :::tip
11
-
12
- Use the power of React to create interactive blog posts.
13
-
14
- ```js
15
- <button onClick={() => alert('button clicked!')}>Click me!</button>
16
- ```
17
-
18
- <button onClick={() => alert('button clicked!')}>Click me!</button>
19
-
20
- :::
@@ -1,25 +0,0 @@
1
- ---
2
- slug: welcome
3
- title: Welcome
4
- authors: [slorber, yangshun]
5
- tags: [facebook, hello, docusaurus]
6
- ---
7
-
8
- [Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
9
-
10
- Simply add Markdown files (or folders) to the `blog` directory.
11
-
12
- Regular blog authors can be added to `authors.yml`.
13
-
14
- The blog post date can be extracted from filenames, such as:
15
-
16
- - `2019-05-30-welcome.md`
17
- - `2019-05-30-welcome/index.md`
18
-
19
- A blog post folder can be convenient to co-locate blog post images:
20
-
21
- ![Docusaurus Plushie](./docusaurus-plushie-banner.jpeg)
22
-
23
- The blog supports tags as well!
24
-
25
- **And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
@@ -1,17 +0,0 @@
1
- endi:
2
- name: Endilie Yacop Sucipto
3
- title: Maintainer of Docusaurus
4
- url: https://github.com/endiliey
5
- image_url: https://github.com/endiliey.png
6
-
7
- yangshun:
8
- name: Yangshun Tay
9
- title: Front End Engineer @ Facebook
10
- url: https://github.com/yangshun
11
- image_url: https://github.com/yangshun.png
12
-
13
- slorber:
14
- name: Sébastien Lorber
15
- title: Docusaurus maintainer
16
- url: https://sebastienlorber.com
17
- image_url: https://github.com/slorber.png
@@ -1,62 +0,0 @@
1
- # GraphQL Overview
2
-
3
- GraphQL allows us to query data from WordPress, without resorting to writing too much PHP code.
4
-
5
- In short, GraphQL allows for the creation of a 'schema', which is a definition of the data available on the server, and 'queries' which actually query that schema. We use the [WPGraphQL](https://www.wpgraphql.com/) WordPress plugin, installed via composer, to provide an automatically generated schema — so all we need to worry about is writing 'queries'.
6
-
7
- Our `eddev-php` library provides additional schema generation, mainly for Gutenberg blocks.
8
-
9
- The WPGraphQL docs are a great place to learn about GraphQL and how WPGraphQL works:
10
-
11
- - [Intro to GraphQL](https://www.wpgraphql.com/docs/intro-to-graphql/)
12
- - [Interacting with WPGraphQL](https://www.wpgraphql.com/docs/interacting-with-wpgraphql/)
13
-
14
- ## GraphiQL IDE
15
-
16
- The GraphiQL IDE built into WPGraphQL provides a window into the schema.
17
-
18
- The IDE also allows you to construct and execute queries, by selecting fields on the left. You can copy/paste between the IDE and your `.graphql` files.
19
-
20
- ![GraphQL IDE](./img/graphql-ide.png)
21
-
22
- ## GraphQL Files
23
-
24
- There are a few locations where `.graphql` query files can be placed within your project's codebase.
25
-
26
- ### Global Data
27
-
28
- You can use `/views/_app.graphql` to declare global data used by your application, and access it from any view/block/component using the `useAppData` hook.
29
-
30
- [Read More &rarr;](/docs/views/app-view)
31
-
32
- ### Views
33
-
34
- 'Views' work just like regular WordPress templates. Instead of `single.php`, you can create a `views/single.tsx` file. Alongside your `.tsx` file, you can create a `.graphql` file with the same name as the `.tsx` file. These queries are automatically executed when the relevant page is accessed.
35
-
36
- [Read More &rarr;](/docs/views/queries)
37
-
38
- ### Blocks
39
-
40
- Just like views, blocks can have a paired `.graphql` file, which is executed automatically for each block.
41
-
42
- [Read More &rarr;](/docs/gutenberg/block-graphql)
43
-
44
- ## Query Hooks
45
-
46
- Sometimes you need to be able to run queries _dynamically_ in the browser, rather than as part of a 'view' or 'block'. This is particularly useful for things like searching and filtering.
47
-
48
- You can place `.graphql` files in `queries/*.graphql`, and hooks will be automatically generated for you to use within your app.
49
-
50
- [Read More &rarr;](/docs/graphql/query-hooks)
51
-
52
- ### Fragments
53
-
54
- Fragments must be stored within `/queries/fragments/*.graphql`
55
-
56
- [GraphQL Fragments](https://graphql.org/learn/queries/#fragments) allow us to write query fragments, which can be reused in multiple files.
57
-
58
- - [Learn more about GraphQL Fragments](https://graphql.org/learn/queries/#fragments)
59
-
60
- ## TypeScript Generation
61
-
62
- TBA
@@ -1,238 +0,0 @@
1
- # Query Hooks
2
-
3
- Sometimes you might need to perform queries at runtime, rather than as part of views or blocks. This is particularly useful for things like searching and filtering.
4
-
5
- To do so, you can create `.graphql` files inside the `queries/` folder.
6
-
7
- React Hooks are automatically generated, based on the name of the query.
8
-
9
- ### Naming Conventions
10
-
11
- For conventions sake, all `queries/*.graphql` files (except for `queries/fragments/*.graphql`) should be start with `use` (eg. `queries/UseLatestPosts.graphql`). Our dev tooling will actually complain if this isn't the case!
12
-
13
- Similarly, the name of your query file and query operation name should also match! Again, you'll get a nice error message if they don't asking you to rename either the operation name, or the file name.
14
-
15
- For example:
16
-
17
- ```graphql title="queries/UseLatestPosts.graphql"
18
- query UseLatestPosts {
19
- posts(first: 10) {
20
- nodes {
21
- id
22
- title(format: RENDERED)
23
- }
24
- }
25
- }
26
- ```
27
-
28
- ### Using your hook
29
-
30
- Generated hooks are stored in `hooks/queries.ts`, and can be imported from there using the name of the query file.
31
-
32
- ```tsx
33
- import { useLatestPosts } from "@hooks/queries"
34
- import { PostTile } from "@components/PostTile"
35
-
36
- export function LatestPosts() {
37
- const results = useLatestPosts()
38
-
39
- if (results.loading) {
40
- return <p>Loading...</p>
41
- }
42
-
43
- if (results.errors) {
44
- return <p>Error!</p>
45
- }
46
-
47
- return (
48
- <div>
49
- {results.data?.posts?.nodes?.map((post) => (
50
- <PostTile key={post.id} post={post} />
51
- ))}
52
- </div>
53
- )
54
- }
55
- ```
56
-
57
- Easy as!
58
-
59
- ### Types of hooks
60
-
61
- There are **three** types of hooks which are automatically generated.
62
-
63
- #### Regular hooks
64
-
65
- The `useLatestPosts` example above is a regular hook. The hook will return an object with the following properties:
66
-
67
- - `loading` (boolean) — whether the query is currently loading
68
- - `errors` (array of error objects) — an array of errors, or `undefined` if there are none. The errors may either be HTTP errors, or GraphQL errors.
69
- - `data` (object) — the data returned by the query, which should be statically typed already based on your GraphQL schema and query.
70
- - `refresh` (function) — a function you can call to re-run the query.
71
-
72
- #### Infinite hooks
73
-
74
- Infinite hooks are a special kind of hook which we've invented, which support infinite loading patterns, such as infinite scrolling and 'load more' buttons.
75
-
76
- Any query which has `Infinite` in the name (eg. `UseInfinitePosts`) will be automatically generated as an infinite hook. These hooks have a `loadMore` function, and make use of the `nodes` and `pageInfo` fields provided by WPGraphQL, and use 'cursor based' pagination.
77
-
78
- There are a few special requirements for infinite hooks, but we've configured the `dev` tooling to warn you if you're not following these conventions (on top of the usual naming convention requirements)
79
-
80
- - The query name must contain the word 'Infinite' (eg. `UseInfinitePosts`)
81
- - There must be a `$limit: Int` variable defined on the query, with a default value. This is the number of items to load per page.
82
- - There must be a `$cursor: String` variable defined on the query, with no default value. This is used for controlling pagination.
83
- - The `$cursor` variable must be used in the `after` field of the query.
84
- - The `$limit` variable must be used in the `first` field of the query.
85
- - Your query must select `nodes`
86
- - Your query must select the `endCursor` and `hasNextPage` fields from the `pageInfo` object
87
-
88
- Here's an example query which fits all of those requirements (it's pretty simple!):
89
-
90
- ```graphql title="queries/UseInfinitePosts.graphql"
91
- query UseInfinitePosts($limit: Int = 2, $cursor: String) {
92
- posts(first: $limit, after: $cursor) {
93
- nodes {
94
- title(format: RENDERED)
95
- }
96
- pageInfo {
97
- endCursor
98
- hasNextPage
99
- }
100
- }
101
- }
102
- ```
103
-
104
- The return value of the hook will be an object with the following properties:
105
-
106
- - `loading` (boolean) — whether the hook is performing it's _first_ load
107
- - `loadingMore` (boolean) — whether the hook is loading additional entries, in response to `loadMore()`
108
- - `errors` (array of error objects) — an array of errors, or `undefined` if there are none. The errors may either be HTTP errors, or GraphQL errors.
109
- - `items` (array of objects) — an array of items, which are the result of the query, automatically extracted from the `nodes` field present in the query
110
- - `hasMore` (boolean) — whether or not there are more items which can be loaded
111
- - `loadMore` (function) — function which can be called to load more items.
112
- - `refresh` (function) — clears out all items, and re-runs the query.
113
-
114
- In essense, you can use `.items` to grab the current items, and `.loadMore()` to load more items when a button is clicked, or an `IntersectionObserver` intersects.
115
-
116
- Heres' an example component which uses the query above:
117
-
118
- ```tsx title="components/LatestPosts.tsx"
119
- import { useInfinitePosts } from "@hooks/queries"
120
-
121
- function InfiniteExample() {
122
- const posts = useInfinitePosts()
123
-
124
- if (posts.loading) {
125
- // The initial load is in progress, show some loading indicator
126
- return <div>Loading...</div>
127
- }
128
-
129
- return (
130
- <div>
131
- {/* The list of items, which will grow as more items are loaded */}
132
- <ul>
133
- {posts.items?.map((item, key) => {
134
- return <li key={key}>{item.title}</li>
135
- })}
136
- </ul>
137
- {/* A 'Load more' button, which is disabled and shows 'Loading...' when more items are loading */}
138
- {posts.hasMore && (
139
- <button disabled={posts.loadingMore} onClick={() => posts.loadMore()}>
140
- {posts.loadingMore ? "Loading..." : "Load more"}
141
- </button>
142
- )}
143
- </div>
144
- )
145
- }
146
- ```
147
-
148
- It looks something like this:
149
-
150
- ![Mutation Example](./img/infinite-example.gif)
151
-
152
- #### Mutation hooks
153
-
154
- Mutation hooks are hooks generated when your operation uses `mutation` in instead of `query`. Mutations are used in GraphQL when the query has some kind of side effect, such as creating a new comment, or submitting a form. Unlike `query` operations, mutations are never cached on the server.
155
-
156
- Mutation hooks return an object with the following properties:
157
-
158
- - `submitting` (boolean) — whether the mutation is currently running
159
- - `submitted` (boolean) — whether or not the last mutation which was submitted completed successfully
160
- - `errors` (array of error objects) — an array of errors, or `undefined` if there are none. The errors may either be HTTP errors, or GraphQL errors.
161
- - `data` (object) — the result of the last submitted mutation, if it was successful.
162
- - `submit(args)` (function) — the function which you must trigger to actually run the mutation. Pass in required parameters as an object.
163
-
164
- An example mutation operation looks like this:
165
-
166
- ```graphql title="queries/UseCreateComment.graphql"
167
- mutation UseSubmitComment($input: CreateCommentInput!) {
168
- createComment(input: $input) {
169
- success
170
- }
171
- }
172
- ```
173
-
174
- Unlike query hooks, the query won't run automatically when using the hook — rather, it needs to be triggered manually using an event or an effect using the `submit` method, provided by the hook.
175
-
176
- ```tsx title="components/CreateComment.tsx"
177
- import { useSubmitComment } from "@hooks/queries"
178
- import { useState } from "react"
179
-
180
- type Props = {
181
- postID: number
182
- }
183
-
184
- export function CreateComment(props: Props) {
185
- const [message, setMessage] = useState("")
186
- const [authorName, setAuthorName] = useState("")
187
- const comment = useSubmitComment()
188
-
189
- return (
190
- <form
191
- onSubmit={(e) => {
192
- e.preventDefault()
193
- comment.submit({
194
- input: {
195
- commentOn: props.postID,
196
- content: message,
197
- approved: null,
198
- author: authorName,
199
- authorEmail: null,
200
- authorUrl: null,
201
- clientMutationId: null,
202
- date: null,
203
- parent: null,
204
- type: null,
205
- },
206
- })
207
- }}
208
- >
209
- {comment.errors && <div>ERROR: {comment.errors[0].message}</div>}
210
- {comment.submitted && <div>Thanks for your comment!</div>}
211
- <input
212
- placeholder="Enter your name"
213
- type="text"
214
- value={authorName}
215
- onChange={(e) => setAuthorName(e.currentTarget.value)}
216
- />
217
- <textarea placeholder="Enter your comment" value={message} onChange={(e) => setMessage(e.currentTarget.value)} />
218
- <button disabled={comment.submitting} type="submit">
219
- Submit comment
220
- </button>
221
- </form>
222
- )
223
- }
224
- ```
225
-
226
- It looks something like this:
227
-
228
- ![Mutation Example](./img/mutation-example.gif)
229
-
230
- ## Does this use the GraphQL endpoint?
231
-
232
- Nope it doesn't! It uses the WP-JSON REST endpoint, and the query file is loaded from the theme folder and executed by the server.
233
-
234
- For example, if you've got a GraphQL file called `queries/UseLatestPosts.graphql` in your theme folder, you'll can actually see it in action by accessing `http://my-site.local/wp-json/ed/v1/query/usePosts?params={%22limit%22:1}`, noting that variables are JSON encoded into the URL — this can be great for debugging GraphQL schema extensions. Use Chrome's Network tab to see the request and responses in action.
235
-
236
- The reason for this is so that the query results can be cached by Flywheel or CloudFlare, and also keeps our `/graphql` hidden from hackers who might want to DDoS the site, or otherwise attempt to scrape data directly from us. The result is that only the data we chose to make public is publicly accessible.
237
-
238
- Mutations also follow this pattern, however they use POST requests, so that data will never accidentally be cached.
@@ -1,3 +0,0 @@
1
- # Extending the GraphQL Schema
2
-
3
- This needs writing, sorry!
@@ -1,4 +0,0 @@
1
- {
2
- "label": "❄️ GraphQL",
3
- "position": 5
4
- }
@@ -1,25 +0,0 @@
1
- # Blocks Overview
2
-
3
- Blocks are primarily defined in a `.tsx` file inside the `blocks/` folder. Blocks should be organised within subfolders, depending on their purpose and context.
4
-
5
- For example:
6
-
7
- - `blocks/layout/section.tsx`
8
- - `blocks/projects/single-project-tile.tsx`
9
- - `blocks/content/button-row.tsx`
10
-
11
- ## ACF Fields
12
-
13
- ACF fields can be attached to any block type. Use ACF fields for complex data.
14
-
15
- ACF fields are passed **directly** to blocks — rather the ACF fields must be selected using GraphQL files. This may seem like a bunch of work, but it actually gives us the opportunity to pull the exact data we need — for example, we can pull metadata for posts directly from 'Post Object' fields. It also allows us to have great TypeScript support for all ACF fields attached to a block, automatically.
16
-
17
- [Read more &rarr;](./block-acf)
18
-
19
- ## GraphQL
20
-
21
- Each block can have a single `.graphql` file sitting alongside the `.tsx` file (eg. `/blocks/sections/newsletter.tsx` and `/blocks/sections/newsletter.graphql`)
22
-
23
- The GraphQL file can query any data from the CMS, as well as any ACF fields attached to the block.
24
-
25
- [Read more &rarr;](./block-graphql)
@@ -1,37 +0,0 @@
1
- # Defining a Block
2
-
3
- Create a new block file, for example `blocks/layout/section.tsx`
4
-
5
- Copy and paste the code below, making sure to:
6
-
7
- - Replace the `TITLE` and `DESCRIPTION`
8
- - Replace `NAME` with the filename of your block (eg. `layouts/section`)
9
- - Run `yarn generate`, so that TypeScript knows what prop types to expect for your new block, and will also validate the name.
10
-
11
- ```tsx title="/blocks/layouts/section.tsx"
12
- /**
13
- * Title: TITLE
14
- * Description: DESCRIPTION
15
- * Category: common
16
- * Icon: book-alt
17
- * Keywords: post
18
- * Types: page, post
19
- * Mode: preview
20
- * Supports multiple: true
21
- * Tags: root
22
- * Child tags: none
23
- */
24
- import { defineBlock } from "eddev/blocks"
25
-
26
- export default defineBlock("NAME", (props) => {
27
- return <div>Hello!</div>
28
- })
29
- ```
30
-
31
- :::tip
32
- Make sure `yarn dev` is running! It'll auto-generate TypeScript types for block when you create it, and it'll continue to update those types if you're using a GraphQL for your block (which you probably are).
33
- :::
34
-
35
- :::warning
36
- If you get a red squiggly next to the block name in the `defineBlock`, it means you're either not running `yarn dev`, or you may be using the wrong name for the current file.
37
- :::