eddev 0.2.26 → 0.2.29

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 (112) hide show
  1. package/admin/components/ImageWell.d.ts +1 -0
  2. package/build/serverless/create-next-app.js +5 -5
  3. package/cli/display/components/BundleDisplay.d.ts +1 -0
  4. package/cli/display/components/CodegenDisplay.d.ts +1 -0
  5. package/cli/display/components/DevCLIDisplay.d.ts +1 -0
  6. package/cli/display/components/ServerlessDisplay.d.ts +1 -0
  7. package/cli/display/components/StatusIcon.d.ts +1 -0
  8. package/components/AdminBar.d.ts +1 -0
  9. package/dev-ui/components/BreakpointColumnHeader.d.ts +1 -0
  10. package/dev-ui/components/BreakpointIndicator.d.ts +1 -0
  11. package/dev-ui/components/DevUI.d.ts +1 -0
  12. package/dev-ui/components/ResponsiveLerpControl.d.ts +1 -0
  13. package/dev-ui/components/ResponsiveScaleEditor.d.ts +1 -0
  14. package/dev-ui/components/atoms/NumberField.d.ts +1 -0
  15. package/dev-ui/components/panels/PageDataDebugger.d.ts +1 -0
  16. package/dev-ui/components/panels/SpacingEditor.d.ts +1 -0
  17. package/dev-ui/components/panels/TypographyEditor.d.ts +1 -0
  18. package/dev-ui/icons.d.ts +1 -0
  19. package/dev-ui/loader.d.ts +1 -0
  20. package/dev-ui/theme.d.ts +3 -2
  21. package/dynamic/dynamic-component.d.ts +1 -0
  22. package/entry/Root.d.ts +1 -0
  23. package/gravityforms/useGravityForm.js +13 -3
  24. package/package.json +4 -3
  25. package/style/createStitches.d.ts +3 -2
  26. package/docs_old/README.md +0 -33
  27. package/docs_old/babel.config.js +0 -3
  28. package/docs_old/blog/2019-05-28-first-blog-post.md +0 -12
  29. package/docs_old/blog/2019-05-29-long-blog-post.md +0 -44
  30. package/docs_old/blog/2021-08-01-mdx-blog-post.mdx +0 -20
  31. package/docs_old/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  32. package/docs_old/blog/2021-08-26-welcome/index.md +0 -25
  33. package/docs_old/blog/authors.yml +0 -17
  34. package/docs_old/docs/graphql/1.graphql-overview.md +0 -62
  35. package/docs_old/docs/graphql/2.query-hooks.md +0 -238
  36. package/docs_old/docs/graphql/3.extending-wpgraphql.md +0 -3
  37. package/docs_old/docs/graphql/_category_.json +0 -4
  38. package/docs_old/docs/graphql/img/graphql-ide.png +0 -0
  39. package/docs_old/docs/graphql/img/infinite-example.gif +0 -0
  40. package/docs_old/docs/graphql/img/mutation-example.gif +0 -0
  41. package/docs_old/docs/gutenberg/1.overview.md +0 -25
  42. package/docs_old/docs/gutenberg/2.block-definition.md +0 -37
  43. package/docs_old/docs/gutenberg/3.block-acf.md +0 -13
  44. package/docs_old/docs/gutenberg/4.block-graphql.md +0 -63
  45. package/docs_old/docs/gutenberg/5.inline-editing.md +0 -33
  46. package/docs_old/docs/gutenberg/6.nested-blocks.md +0 -80
  47. package/docs_old/docs/gutenberg/7.restricting-to-post-types.md +0 -38
  48. package/docs_old/docs/gutenberg/8.restricting-to-page-templates.md +0 -26
  49. package/docs_old/docs/gutenberg/9.dynamic-blocks.md +0 -21
  50. package/docs_old/docs/gutenberg/_category_.json +0 -4
  51. package/docs_old/docs/gutenberg/img/create-acf-fields-for-block.png +0 -0
  52. package/docs_old/docs/gutenberg/img/example-acf-single-project-tile.png +0 -0
  53. package/docs_old/docs/how-to/1.new-site.md +0 -36
  54. package/docs_old/docs/how-to/2.deployment.md +0 -31
  55. package/docs_old/docs/how-to/3.menus.md +0 -72
  56. package/docs_old/docs/how-to/4.options-pages.md +0 -41
  57. package/docs_old/docs/how-to/5.bundle-size.md +0 -177
  58. package/docs_old/docs/how-to/6.favicons.md +0 -82
  59. package/docs_old/docs/how-to/_category_.json +0 -4
  60. package/docs_old/docs/how-to/img/bundle-analysis-after.png +0 -0
  61. package/docs_old/docs/how-to/img/bundle-analysis-before.png +0 -0
  62. package/docs_old/docs/how-to/img/bundle-webpack-after.png +0 -0
  63. package/docs_old/docs/how-to/img/bundle-webpack-before.png +0 -0
  64. package/docs_old/docs/how-to/img/favicon-codebase.png +0 -0
  65. package/docs_old/docs/how-to/img/favicon-figma-export.png +0 -0
  66. package/docs_old/docs/how-to/img/favicon-figma.png +0 -0
  67. package/docs_old/docs/intro.md +0 -7
  68. package/docs_old/docs/known-issues.md +0 -8
  69. package/docs_old/docs/serverless/1.overview.md +0 -1
  70. package/docs_old/docs/serverless/2.config.md +0 -1
  71. package/docs_old/docs/serverless/3.wordpress-vercel.md +0 -8
  72. package/docs_old/docs/serverless/4.apis.md +0 -1
  73. package/docs_old/docs/serverless/5.rpc.md +0 -1
  74. package/docs_old/docs/serverless/_category_.json +0 -4
  75. package/docs_old/docs/stack/1-WordPress.md +0 -18
  76. package/docs_old/docs/stack/2-Flywheel.md +0 -15
  77. package/docs_old/docs/stack/3-React.md +0 -12
  78. package/docs_old/docs/stack/4-TypeScript.md +0 -13
  79. package/docs_old/docs/stack/5-WPGraphQL.md +0 -21
  80. package/docs_old/docs/stack/6-eddev.md +0 -9
  81. package/docs_old/docs/stack/_category_.json +0 -4
  82. package/docs_old/docs/tooling/1.scripts.md +0 -25
  83. package/docs_old/docs/tooling/2.aliases.md +0 -13
  84. package/docs_old/docs/tooling/3.defines.md +0 -13
  85. package/docs_old/docs/tooling/4.config-file.md +0 -14
  86. package/docs_old/docs/tooling/_category_.json +0 -4
  87. package/docs_old/docs/views/1.overview.md +0 -31
  88. package/docs_old/docs/views/2.queries.md +0 -18
  89. package/docs_old/docs/views/3.content-blocks.md +0 -36
  90. package/docs_old/docs/views/4.app-view.md +0 -35
  91. package/docs_old/docs/views/5.page-templates.md +0 -20
  92. package/docs_old/docs/views/_category_.json +0 -4
  93. package/docs_old/docusaurus.config.js +0 -119
  94. package/docs_old/package.json +0 -40
  95. package/docs_old/sidebars.js +0 -26
  96. package/docs_old/src/components/HomepageFeatures.js +0 -64
  97. package/docs_old/src/components/HomepageFeatures.module.css +0 -11
  98. package/docs_old/src/css/custom.css +0 -28
  99. package/docs_old/src/pages/index.js +0 -36
  100. package/docs_old/src/pages/index.module.css +0 -23
  101. package/docs_old/src/pages/markdown-page.md +0 -7
  102. package/docs_old/static/.nojekyll +0 -0
  103. package/docs_old/static/img/docusaurus.png +0 -0
  104. package/docs_old/static/img/favicon.ico +0 -0
  105. package/docs_old/static/img/logo-black.svg +0 -4
  106. package/docs_old/static/img/logo-white.svg +0 -4
  107. package/docs_old/static/img/tutorial/docsVersionDropdown.png +0 -0
  108. package/docs_old/static/img/tutorial/localeDropdown.png +0 -0
  109. package/docs_old/static/img/undraw_docusaurus_mountain.svg +0 -170
  110. package/docs_old/static/img/undraw_docusaurus_react.svg +0 -169
  111. package/docs_old/static/img/undraw_docusaurus_tree.svg +0 -1
  112. package/docs_old/yarn.lock +0 -8814
@@ -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
- :::
@@ -1,13 +0,0 @@
1
- # Block ACF Fields
2
-
3
- Once you've created a `.tsx` file for your block, it'll automatically be registered with WordPress, and is available to be targetted by ACF field groups.
4
-
5
- - Create a new ACF Field Group
6
- - Make sure the block title starts with `Block: ` — this is just convention
7
- - Add any fields you like.
8
-
9
- ![Adding an ACF Field Group for a Block](./img/create-acf-fields-for-block.png)
10
-
11
- :::tip
12
- We may add the ability to have [ACF Builder](https://github.com/StoutLogic/acf-builder) support for blocks at some point, however for now it's recommended that you use the ACF Interface to build fields for your blocks. ACF Builder is an advanced tool which requires that you have a deeper knowledge of ACF and all of it's configuration options, and may be harder to use for ACF newbies.
13
- :::
@@ -1,63 +0,0 @@
1
- # Block GraphQL Files
2
-
3
- ## Naming
4
-
5
- A block named `/blocks/sections/newsletter.tsx` can have a single GraphQL query file named `/blocks/sections/newsletter.graphql`.
6
-
7
- Due to a limitation with GraphQL Codegen, each `.graphql` file must contain one uniquely-named.
8
-
9
- ACF fields attached to the block can be queried using the naming convention `folderName_blockName`, where the folder name and block name are automatically converted from `dash-case` to `camelCase`.
10
-
11
- ## Execution
12
-
13
- Block queries are executed automatically by PHP code, so there is no need to call any functions to get the data, or handle any loading/error state. The result of the query is sent straight into the `props` of your block.
14
-
15
- ## Querying ACF Fields
16
-
17
- GraphQL schemas for your blocks ACF Fields are automatically generated by PHP.
18
-
19
- Consider this block type:
20
-
21
- ```tsx title="blocks/project/single-project-tile.tsx"
22
- /**
23
- * Title: Single Project Tile
24
- * Description: Displays a single project as a large tile.
25
- * Category: common
26
- * Icon: book-alt
27
- * Keywords: post
28
- * Types: page, post
29
- * Mode: preview
30
- * Supports multiple: true
31
- */
32
- import { defineBlock, EditableText, InnerBlocks } from "eddev/blocks"
33
-
34
- export default defineBlock("project/single-project-tile", (props) => {
35
- return <div>...</div>
36
- })
37
- ```
38
-
39
- With the following ACF field configuration:
40
-
41
- ![Example block](./img/example-acf-single-project-tile.png)
42
-
43
- The ACF fields will be available under `block.project_singleProjectTile`
44
-
45
- ```graphql title="blocks/project/single-project-tile.graphql"
46
- query SingleProjectTile {
47
- block {
48
- project_singleProjectTile {
49
- project {
50
- ... on Project {
51
- id
52
- title(format: RENDERED)
53
- projectFields {
54
- image {
55
- ...BasicImage
56
- }
57
- }
58
- }
59
- }
60
- }
61
- }
62
- }
63
- ```
@@ -1,33 +0,0 @@
1
- # Inline Editing
2
-
3
- It's trivial to add inline editing to your blocks. This is totally separate from ACF.
4
-
5
- ## `<EditableText />`
6
-
7
- The most common inline editing function will of course be the ability to edit text in your block. The `<EditableText>` component does just this! Keep in mind, this can only be used on blocks, or components which are used within a block.
8
-
9
- ```tsx
10
- <div>
11
- <EditableText as="h2" id="title" placeholder="Enter a title" />
12
- </div>
13
- ```
14
-
15
- When the above code runs in the WordPress editor, an author can click on that element and type into it directly.
16
-
17
- Note that you can have as many `<EditableText>` components as you want, however each `id` must be unique, since each value is stored as a key/value pair.
18
-
19
- The `as` prop is required, and can either be an element type (`p`, `h1`, `h2`, etc.) or a component.
20
-
21
- ## `useInlineEditableValue`
22
-
23
- The `useInlineEditableValue` hook is the foundation of all inline editing in our system — it works a lot like `useState`, except that the content is saved to the block when saving the page, and restored again when the page is loaded.
24
-
25
- Much like `EditableText`, the hook requires a unique `id` to identify the value.
26
-
27
- You can store any kind of data, including objects and arrays.
28
-
29
- ```tsx
30
- const [title, setTitle] = useInlineEditableValue('title');
31
-
32
- return <input type="text" value={title} onChange={e => setTitle(e.currentTarget.value)}>
33
- ```
@@ -1,80 +0,0 @@
1
- # Nested Blocks
2
-
3
- Nested blocks add a lot of power to Gutenberg — you can create blocks, which themselves contain more blocks.
4
-
5
- The `<InnerBlocks />` component acts as a container for child blocks.
6
-
7
- Note that you can only have ONE `InnerBlocks` per-block. This is a WordPress limitation.
8
-
9
- ## Block Tagging
10
-
11
- Most of the time, we want to restrict where blocks can be used. For example, we might have a set of 'root' blocks which the user can only be added to the root of the page. Then, we might want some 'inline' blocks which can be added to some of those root blocks. We may also have specialised blocks, like a 'Button Row', which can only accept 'Button' blocks.
12
-
13
- To do this, we've invented a 'tags' system for blocks, which is defined in the comments section of a block.
14
-
15
- ```tsx
16
- /*
17
- * ...
18
- * Tags: root
19
- * Child tags: inline
20
- */
21
- ```
22
-
23
- Use 'Tags' to define the tags on this block, as a comma separated list if defining multiple tags. The `'root'` tag is special, in that any block tagged with it can be added to the root of the page.
24
-
25
- If the block has `InnerBlocks`, you can use `Child tags` to indirectly specify the allowed block types which can be added to this block.
26
-
27
- ## Tagging core blocks
28
-
29
- You can also tag core blocks, which are blocks which are included by WordPress, using some PHP code.
30
-
31
- Note that you can tag core blocks multiple times with multiple tags.
32
-
33
- ```php title="backend/blocks.php"
34
- <?php
35
-
36
- ED()->tagCoreBlocks("wysiwyg", [
37
- "core/paragraph",
38
- "core/list",
39
- "core/heading",
40
- ]);
41
-
42
- ?>
43
- ```
44
-
45
- ## Putting it all together
46
-
47
- For example, if you have a 'Section' block which accepts some WYSIWYG blocks like headings and paragraphs as well as a 'Button Row' block, and only want to allow 'Button' blocks to be added to the 'Button Row', you might have something like this:
48
-
49
- ```tsx title="blocks/layout/section.tsx"
50
- /*
51
- * ...
52
- * Tags: root
53
- * Child tags: inline, wysiwyg
54
- */
55
- ```
56
-
57
- ```tsx title="blocks/buttons/button-row.tsx"
58
- /*
59
- * ...
60
- * Tags: inline
61
- * Child tags: buttons
62
- */
63
- ```
64
-
65
- ```tsx title="blocks/buttons/button.tsx"
66
- /*
67
- * ...
68
- * Tags: buttons
69
- */
70
- ```
71
-
72
- ```php title="backend/blocks.php"
73
-
74
- ED()->tagCoreBlocks("wysiwyg", [
75
- "core/paragraph",
76
- "core/list",
77
- "core/heading",
78
- ]);
79
-
80
- ```
@@ -1,38 +0,0 @@
1
- # Restricting to Post Types
2
-
3
- You can restrict an individual block type to only be used in certain post types.
4
-
5
- To do this, just update your block's `Types` property. You can have multiple types, separated by commas.
6
-
7
- ```tsx
8
- /*
9
- * ...
10
- * Types: page, post
11
- * ...
12
- */
13
- ```
14
-
15
- ### Template Locking
16
-
17
- Taking this a step further, you can also specify required root blocks for a post type.
18
-
19
- For example, you might want to specify that when creating a new blog post, that only 'Blog Post Header' and 'Blog Post Content' blocks are added to root, and are automatically added when creating a new post, and also cannot be removed.
20
-
21
- This needs to be done in PHP:
22
-
23
- ```php title="backend/blocks.php"
24
- <?php
25
-
26
- ED()->templateLock([
27
- 'type' => 'post',
28
- 'content' => [
29
- ['acf/blog-post-header'],
30
- ['acf/blog-post-content'],
31
- ]
32
- ]);
33
-
34
- ```
35
-
36
- :::warning
37
- Note that you need to use the internal ACF block name when working with template locks. For example, `blog/post-header` becomes `acf/blog-post-header`.
38
- :::
@@ -1,26 +0,0 @@
1
- # Restricting to Page Templates
2
-
3
- You can restrict an individual block type to only be used in certain page templates
4
-
5
- To do this, just update your block's `Templates` property. You can have multiple templates, separated by commas.
6
-
7
- ```tsx
8
- /*
9
- * ...
10
- * Types: page, post
11
- * Templates: templates/my-cool-template
12
- * ...
13
- */
14
- ```
15
-
16
- :::tip
17
- Be sure to set `Types: page`, otherwise the block wont be available in the page template.
18
- :::
19
-
20
- :::warning
21
- Note that in above example, the block will be available on all `post`s, and all `page`s which have the template `views/templates/my-cool-template.tsx`.
22
- :::
23
-
24
- ### Template Locking
25
-
26
- Unfortunately this isn't possible at the moment... mostly due to Gutenberg being a bit crap.
@@ -1,21 +0,0 @@
1
- # Dynamic Blocks
2
-
3
- A "dynamic" block is a block that loads asynchronously, only when it's used for the first time. This is useful when a block has a large dependency (think, THREE.js or Swiper). This can drastically reduce the size of your bundle, while also improving the loading time of your site.
4
-
5
- The downside is that the block won't load until it's first use, which means that it'll be hidden for a moment while it loads. Because of this, it's recommended that you:
6
-
7
- - Perhaps don't use this feature if your block is likely to be used above-the-fold (maybe a good candidate for dynamic components or dynamic imports)
8
- - Do a fade in animation when the block is first mounted, so that it's not a jarring experience.
9
-
10
- It's super easy to enable this feature — just add `Dynamic: true` to your block header comment.
11
-
12
- ```tsx title="/blocks/layouts/section.tsx"
13
- /**
14
- * Title: TITLE
15
- * Description: DESCRIPTION
16
- * ...etc
17
- * Dynamic: true
18
- */
19
- ```
20
-
21
- You can read more about dynamic _components_, and other ways to reduce your bundle size here — [Bundle Size Tips &rarr;](../how-to/bundle-size)
@@ -1,4 +0,0 @@
1
- {
2
- "label": "🧱 Gutenberg Blocks",
3
- "position": 4
4
- }
@@ -1,36 +0,0 @@
1
- # Creating a new site
2
-
3
- ### Initial Setup
4
-
5
- 1. [Create a new repo on Github](https://github.com/new)
6
- 1. Set `Owner` to `ed-digital`, and name your repo like `some-client-name`.
7
- 2. Set `Repository Template` to `ed-digital/eddev-starter-theme`
8
- 3. Hit `Create repository`
9
- 2. Create a new site in Local, on your computer.
10
- 1. Use the default settings
11
- 2. Be sure to use `ed_admin` as the username, and create a secure password using 1pass or similar, and the email address should be `web@ed.com.au`
12
- 3. Save the username and password to 1pass.
13
- 3. Install the following plugins:
14
- 1. Advanced Custom Fields Pro ([download](https://www.advancedcustomfields.com/my-account/view-licenses/)
15
- 2. Add `b3JkZXJfaWQ9NDA3NDN8dHlwZT1kZXZlbG9wZXJ8ZGF0ZT0yMDE0LTA5LTI3IDA4OjUwOjIx` as the key for ACF Pro under 'Custom Fields > Updates'
16
- 3. Yoast SEO — install from plugins dashboard
17
- 4. Gutenberg — install from plugins dashboard
18
- 5. Nested Pages — install from plugins dashboard
19
- 6. Admin Menu Editor — install from plugins dashboard (use this to hide unused sidebar items, and tidy up the menu for clients.)
20
- 4. Under Settings -> General, remove 'Just another WordPress Site' and set Timezone to Sydney.
21
- 6. Make sure that all the installed plugins have been activated.
22
- 7. Clone your newly created theme to `wp-content/themes/`, making sure that the repo name and the theme folder name are identical.
23
- 8. Run the following commands inside the theme folder
24
- 1. `composer update`
25
- 2. `yarn`
26
- 3. `yarn add --dev eddev`
27
- 4. `yarn setup`
28
- 9. Activate the theme under Appearance > Themes
29
- 10. Run `yarn dev`
30
-
31
- ### Initial Flywheel Setup
32
-
33
- 1. [Create a new site on Flywheel](https://app.getflywheel.com/new-site)
34
- 1. Select 'My Organisation'
35
- 2. The username and password are irrelevant, as they'll soon be overridden with your locally created details.
36
- 2. Once complete, restart Local, and do an initial push to the new site, deploying to 'Production' with 'Include Database' selected.