Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Post level components to allow easy building of page level blocks #178

Merged
merged 122 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
3bbb90a
add new property to image component to show placeholder without uploa…
fabiankaegy Dec 9, 2022
352c7d7
add use post hook to get correct post within query loop
fabiankaegy Dec 9, 2022
31044e9
add useCanEditEntity hook
fabiankaegy Dec 9, 2022
2bf1a97
add useIsSupportedTaxonomy hook
fabiankaegy Dec 9, 2022
941a4d9
add hooks to get selected terms
fabiankaegy Dec 9, 2022
abab9d3
add useIsPluginActive hook to check whether a plugin is active
fabiankaegy Dec 9, 2022
28e6303
add usePrimaryTerm hook which works with Yoast SEO Primary Term Feature
fabiankaegy Dec 9, 2022
72d8def
add usePropover hook to easily add popovers to elements
fabiankaegy Dec 9, 2022
87742f3
add PostTitle component
fabiankaegy Dec 9, 2022
67c2ea1
add PostFeaturedImage component
fabiankaegy Dec 9, 2022
8e133ec
add PostExcerpt component
fabiankaegy Dec 9, 2022
ab52565
add PostAuthor component
fabiankaegy Dec 9, 2022
c4a0227
add PostDate and PostDatePicker components
fabiankaegy Dec 9, 2022
c64112e
add PostCategories component
fabiankaegy Dec 9, 2022
a99e313
add PostPrimaryCategory component which interacts with Yoast SEO prim…
fabiankaegy Dec 9, 2022
59ac2eb
add PostTerms component
fabiankaegy Dec 9, 2022
9f544d1
refactor PostCategories component to use PostTerms
fabiankaegy Dec 9, 2022
5743a08
add PostPrimaryTerm component
fabiankaegy Dec 9, 2022
aa20ab6
refactor PostPrimaryCategory with PostPrimaryTerm
fabiankaegy Dec 9, 2022
e778cae
add example block for post title component
fabiankaegy Dec 9, 2022
e1b0f90
add example post for post featured image component
fabiankaegy Dec 9, 2022
56ebd6f
add exampel block for a content item / card component using the post …
fabiankaegy Dec 9, 2022
140c68f
add an example hero block using the post level components
fabiankaegy Dec 9, 2022
6ff0b63
install Yoast SEO plugin in the example project
fabiankaegy Dec 9, 2022
64aefa6
fix popover linting issue
fabiankaegy Dec 9, 2022
589018b
1.14.2-alpha.0
fabiankaegy Dec 9, 2022
b04b0c0
fix use tagName as prop name over as
fabiankaegy Dec 12, 2022
62c9c2f
refactor post term list
fabiankaegy Dec 12, 2022
5f44f85
fix render callback and default markup of term list
fabiankaegy Dec 12, 2022
2aaa26f
logical refactors
fabiankaegy Dec 12, 2022
34aca1f
add base readme files
fabiankaegy Dec 12, 2022
bad8cf4
fix title rendering performance
fabiankaegy Dec 12, 2022
099a607
1.14.2-alpha.1
fabiankaegy Dec 12, 2022
a8e2dd0
add PostContext component
fabiankaegy Dec 13, 2022
51630aa
fix propTypes of PostCategoryList
fabiankaegy Dec 13, 2022
b4bb572
fix propTypes of PostPrimaryCategory
fabiankaegy Dec 13, 2022
d11a0e4
fix refactor components away from passign through context
fabiankaegy Dec 13, 2022
1f07d1b
fix import path for all components
fabiankaegy Dec 13, 2022
26d913a
fix use correct isEditable factor
fabiankaegy Dec 13, 2022
77a856d
refactor post context context
fabiankaegy Dec 13, 2022
2f4c01e
fix remove unused proptypes
fabiankaegy Dec 13, 2022
3082a91
fix use inert for disabled elements
fabiankaegy Dec 13, 2022
8a82786
allow usage of custom date format
fabiankaegy Dec 13, 2022
19f4d79
Merge branch 'develop' into feature/post-level-components
fabiankaegy Dec 15, 2022
78669b4
Merge branch 'develop' into feature/post-level-components
fabiankaegy Dec 15, 2022
c443c8a
Merge branch 'develop' into feature/post-level-components
fabiankaegy Dec 15, 2022
296fb7b
fix remove duplicate import caused by false merge resoluton
fabiankaegy Dec 15, 2022
84216fc
ensure yoast SEO panel is hidden before running tests
fabiankaegy Dec 15, 2022
13d0f9d
Merge branch 'develop' into feature/post-level-components
fabiankaegy Dec 15, 2022
9940a09
Merge branch 'develop' into feature/post-level-components
fabiankaegy Jan 9, 2023
3e78483
1.14.4-alpha.0
fabiankaegy Jan 9, 2023
424f4f1
1.14.4-alpha.1
fabiankaegy Jan 9, 2023
55ec429
1.14.4-alpha.2
fabiankaegy Jan 9, 2023
0bb3aa0
Merge branch 'develop' into feature/post-level-components
fabiankaegy Jan 18, 2023
ad24c3f
1.14.5-alpha.0
fabiankaegy Jan 18, 2023
a4564cf
fix always register icons only when the browser is ready
fabiankaegy Jan 18, 2023
448fbed
Merge branch 'develop' into feature/post-level-components
fabiankaegy Jan 18, 2023
2c877b3
removed unused hook
fabiankaegy Jan 18, 2023
3c7c154
add readme for useAllTerms hook
fabiankaegy Jan 18, 2023
0453c46
add readme for useIsPluginActive hook
fabiankaegy Jan 18, 2023
0663e2b
add readme for useIsSupportedTaxonomy hook
fabiankaegy Jan 18, 2023
74528d0
add readme for usePopover hook
fabiankaegy Jan 18, 2023
7d77118
add readme to usePost hook
fabiankaegy Jan 18, 2023
7fc3e90
add readme for usePrimaryTerm hook
fabiankaegy Jan 18, 2023
4f0f198
fix description of usePrimaryTerm readme
fabiankaegy Jan 18, 2023
ee459e1
add readme for useSelectedTermIds hook
fabiankaegy Jan 18, 2023
7b91d9c
add readme for useSelectedTerms hook
fabiankaegy Jan 18, 2023
d4bee9a
add readme for useSelectedTermsOfSavedPost hook
fabiankaegy Jan 18, 2023
8e3b28e
fix Author components markup
fabiankaegy Jan 18, 2023
e116fc8
add more docs to PostAuthor component
fabiankaegy Jan 18, 2023
a9b9d42
add more detailed docs
fabiankaegy Jan 18, 2023
5058d53
add new hooks and components to main readme
fabiankaegy Jan 18, 2023
f8eeed6
fix formatting in readme
fabiankaegy Jan 18, 2023
d6d96a4
add more detail to PostCategoryList readme
fabiankaegy Jan 18, 2023
c3b0b2d
add more context
fabiankaegy Jan 18, 2023
d9e99dc
Add yoast warning
fabiankaegy Jan 18, 2023
93427d6
Merge branch 'develop' into feature/post-level-components
fabiankaegy Jan 18, 2023
9b0151c
Merge branch 'develop' into feature/post-level-components
fabiankaegy Jan 25, 2023
ddf08fe
1.14.6-alpha.0
fabiankaegy Jan 25, 2023
45e80cf
add docs for subcomponents of post term list
fabiankaegy Jan 25, 2023
4ecfaa8
expand documentation of PostContext component
fabiankaegy Jan 25, 2023
1469ac6
add more context to post context docs
fabiankaegy Jan 25, 2023
536ff25
add more context to post featured image component
fabiankaegy Jan 25, 2023
32cdfa1
fix issue in title component readme
fabiankaegy Jan 25, 2023
5c85a96
add PostMeta component
fabiankaegy Jan 25, 2023
4b75a51
add example block for PostMeta component
fabiankaegy Jan 25, 2023
60e39dd
fix allow usage of render function inside post meta component
fabiankaegy Jan 25, 2023
f2fb415
fix docs of postMeta component
fabiankaegy Jan 25, 2023
b1666bf
fix link component test
fabiankaegy Jan 30, 2023
8e6cf06
1.14.6-alpha.1
fabiankaegy Feb 2, 2023
4372a90
Merge branch 'develop' into feature/post-level-components
fabiankaegy Feb 10, 2023
dd17d63
fix refacor useIsPluginActive to only query for individual plugin
fabiankaegy Feb 15, 2023
24ec39b
1.14.6-alpha.2
fabiankaegy Feb 15, 2023
b35dbdf
fix support network-active plugins in useIsPluginActive hook
fabiankaegy Feb 15, 2023
cae99a7
1.14.6-alpha.3
fabiankaegy Feb 15, 2023
bb6dce9
add new useTaxonomy hook
fabiankaegy Feb 15, 2023
5b4a386
fix use correct hierarchical or flat term selector
fabiankaegy Feb 15, 2023
37ae86b
fix import path in example
fabiankaegy Feb 15, 2023
18512dc
1.14.6-alpha.4
fabiankaegy Feb 15, 2023
49de9cb
fix add missing reference to main readme file
fabiankaegy Feb 15, 2023
61d03b3
fix remove disabeling of eslint rule
fabiankaegy Feb 15, 2023
474dba2
fix rename PostContext to use PascalCase
fabiankaegy Feb 15, 2023
437b832
fix rename PostTermItemContext to use PascalCase
fabiankaegy Feb 15, 2023
31e668a
fix rename AuthorContext to use PascalContext
fabiankaegy Feb 15, 2023
3b4e115
fix delete unused context definition
fabiankaegy Feb 15, 2023
326ab5f
fix rename PostTermItemContext to PostTermContext
fabiankaegy Feb 15, 2023
35d0436
fix remove redundant default value covered by defaultProps
fabiankaegy Feb 15, 2023
fcb479e
add more detail to PostContext readme about `usesContext`
fabiankaegy Feb 15, 2023
b715084
add more context to PostContext readme about updating external post
fabiankaegy Feb 15, 2023
e4198d1
Update components/post-context/readme.md
fabiankaegy Feb 15, 2023
25d251f
Update components/post-meta/readme.md
fabiankaegy Feb 15, 2023
5d416d9
fix indentation of code example in readme
fabiankaegy Feb 15, 2023
9558467
fix formatting issues in post featured image block example
fabiankaegy Feb 15, 2023
27c0ffc
fix use defaultProps over inline defaults in PostPrimaryTerm component
fabiankaegy Feb 15, 2023
e278bce
fix remove duplicate defaultProps definition in PostPrimaryCategory c…
fabiankaegy Feb 15, 2023
c853dff
fix rely on defaultProps over inline defaults in PostDate component
fabiankaegy Feb 15, 2023
b56e790
fix rely on defaultProps over inline default in PostExcerpt component
fabiankaegy Feb 15, 2023
e6f5599
fix rely on defaultProps over inline default in MetaString component
fabiankaegy Feb 15, 2023
dea9396
fix rely on defaultProps over inline default in PostTermList component
fabiankaegy Feb 15, 2023
732d5d1
fix rely on defaultProps over inline default in ListItem component
fabiankaegy Feb 15, 2023
e55a455
fix rely on defaultProps over inline default in PostTitle component
fabiankaegy Feb 15, 2023
3682e78
1.14.6-alpha.5
fabiankaegy Feb 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ A collection of components built to be used in the block editor. These component
- [Repeater](./components/repeater/)
- [RichTextCharacterLimit](./components/rich-text-character-limit)

### Post related Components

These components read/write information from the global post object or a `PostContext`.

- [PostAuthor](./components/post-author/)
- [PostCategoryList](./components/post-category-list/)
- [PostContext](./components/post-context/)
- [PostDate](./components/post-date)
- [PostExcerpt](./components/post-excerpt/)
- [PostFeaturedImage](./components/post-featured-image/)
- [PostPrimaryCategory](./components/post-primary-category/)
- [PostPrimaryTerm](./components/post-primary-term/)
- [PostTermList](./components/post-term-list/)
- [PostTitle](./components/post-title/)
- [PostMeta](./components/post-meta/)

## Hooks

- [useFilteredList](./hooks/use-filtered-list)
Expand All @@ -46,6 +62,22 @@ A collection of components built to be used in the block editor. These component
- [useRequestData](./hooks/use-request-data/)
- [useBlockParentAttributes](./hooks/use-block-parent-attributes/)
- [useScript](./hooks/use-script/)
- [useIsPluginActive](./hooks/use-is-plugin-active/)
- [usePopover](./hooks/use-popover/)

### Post related hooks

These hooks read/write information from the global post object or a `PostContext`.

- [useAllTerms](./hooks/use-all-terms/)
- [useTaxonomy](./hooks/use-taxonomy/)
- [useIsSupportedTaxonomy](./hooks/use-is-supported-taxonomy/)
- [usePost](./hooks/use-post/)
- [usePrimaryTerm](./hooks/use-primary-term/)
- [useSelectedTermIds](./hooks/use-selected-term-ids/)
- [useSelectedTerms](./hooks/use-selected-terms/)
- [useSelectedTermsOfSavedPost](./hooks/use-selected-terms-of-saved-post/)
- [usePostMetaValue](./hooks/use-post-meta-value/)

## Stores

Expand Down
5 changes: 4 additions & 1 deletion api/register-icons/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { dispatch } from '@wordpress/data';
import domReady from '@wordpress/dom-ready';

import { iconStore } from '../../stores';

export function registerIcons(options) {
dispatch(iconStore).registerIconSet(options);
domReady(() => {
dispatch(iconStore).registerIconSet(options);
});
}
3 changes: 3 additions & 0 deletions components/author/context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createContext } from '@wordpress/element';

export const AuthorContext = createContext();
144 changes: 144 additions & 0 deletions components/author/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { useContext } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
import PropTypes from 'prop-types';
import { AuthorContext } from './context';

/**
* @typedef {object} Author
* @property {object} author
* @property {object<string, string>} author.avatar_urls
* @property {string} author.description
* @property {string} author.email
* @property {string} author.first_name
* @property {number} author.id
* @property {string} author.last_name
* @property {string} author.link
* @property {string} author.name
* @property {string} author.nickname
* @property {string} author.registered_date
* @property {string} author.slug
* @property {string} author.url
*/

export const Name = (props) => {
const { tagName: TagName, ...rest } = props;

/**
* @type {Author}
*/
const { name, link } = useContext(AuthorContext);

const wrapperProps = { ...rest };

if (TagName === 'a' && link) {
wrapperProps.href = link;
}

return <TagName {...wrapperProps}>{name}</TagName>;
};

Name.propTypes = {
tagName: PropTypes.string,
};

Name.defaultProps = {
tagName: 'span',
};

export const FirstName = (props) => {
const { tagName: TagName, ...rest } = props;

/**
* @type {Author}
*/
const { first_name: firstName } = useContext(AuthorContext);

return <TagName {...rest}>{firstName}</TagName>;
};

FirstName.propTypes = {
tagName: PropTypes.string,
};

FirstName.defaultProps = {
tagName: 'span',
};

export const LastName = (props) => {
const { tagName: TagName, ...rest } = props;

/**
* @type {Author}
*/
const { last_name: lastName } = useContext(AuthorContext);

return <TagName {...rest}>{lastName}</TagName>;
};

LastName.propTypes = {
tagName: PropTypes.string,
};

LastName.defaultProps = {
tagName: 'span',
};

function useDefaultAvatar() {
const { avatarURL: defaultAvatarUrl } = useSelect((select) => {
const { getSettings } = select(blockEditorStore);
const { __experimentalDiscussionSettings } = getSettings();
return __experimentalDiscussionSettings;
});
return defaultAvatarUrl;
}

export const Avatar = (props) => {
const { ...rest } = props;

/**
* @type {Author}
*/
const authorDetails = useContext(AuthorContext);

const avatarUrls = authorDetails?.avatar_urls ? Object.values(authorDetails.avatar_urls) : null;
const defaultAvatar = useDefaultAvatar();

const avatarSourceUrl = avatarUrls ? avatarUrls[avatarUrls.length - 1] : defaultAvatar;

return <img src={avatarSourceUrl} {...rest} />;
};

export const Bio = (props) => {
const { tagName: TagName = 'p', ...rest } = props;

/**
* @type {Author}
*/
const { description } = useContext(AuthorContext);

return <TagName {...rest}>{description}</TagName>;
};

Bio.propTypes = {
tagName: PropTypes.string,
};

Bio.defaultProps = {
tagName: 'p',
};

export const Email = (props) => {
const { ...rest } = props;

/**
* @type {Author}
*/
const { email } = useContext(AuthorContext);

return (
<a href={`mailto:${email}`} {...rest}>
{email}
</a>
);
};
11 changes: 9 additions & 2 deletions components/image/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MediaPlaceholder, InspectorControls } from '@wordpress/block-editor';
import { Spinner, FocalPointPicker, PanelBody } from '@wordpress/components';
import { Spinner, FocalPointPicker, PanelBody, Placeholder } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import PropTypes from 'prop-types';

Expand All @@ -12,14 +12,19 @@ const Image = (props) => {
onSelect,
focalPoint = { x: 0.5, y: 0.5 },
onChangeFocalPoint,
canEditImage = true,
...rest
} = props;
const hasImage = !!id;
const { media, isResolvingMedia } = useMedia(id);

const shouldDisplayFocalPointPicker = typeof onChangeFocalPoint === 'function';

if (!hasImage) {
if (!hasImage && !canEditImage) {
return <Placeholder className="block-editor-media-placeholder" withIllustration />;
}

if (!hasImage && canEditImage) {
return <MediaPlaceholder onSelect={onSelect} accept="image" multiple={false} />;
}

Expand Down Expand Up @@ -67,6 +72,7 @@ Image.defaultProps = {
size: 'large',
focalPoint: { x: 0.5, y: 0.5 },
onChangeFocalPoint: undefined,
canEditImage: true,
};

Image.propTypes = {
Expand All @@ -78,4 +84,5 @@ Image.propTypes = {
x: PropTypes.string,
y: PropTypes.string,
}),
canEditImage: PropTypes.bool,
};
3 changes: 2 additions & 1 deletion components/image/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ function BlockEdit(props) {
| `size` | `string` | `large` | Name of the image size to be displayed |
| `focalPoint` | `object` | `{x:0.5,y:0.5}` | Optional focal point object.
| `onChangeFocalPoint` | `function` | `undefined` | Callback that gets called with the new focal point when it changes. (Is required for the FocalPointPicker to appear) |
| `...rest` | `*` | `null` | Any additional attributes you want to pass to the underlying `img` tag |
| `...rest` | `*` | `null` | any additional attributes you want to pass to the underlying `img` tag |
| `canEditImage` | `boolean` | `true` | whether or not the image can be edited by in the context its getting viewed. Controls whether a placeholder or upload controls should be shown when no image is present |
11 changes: 11 additions & 0 deletions components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,16 @@ export { Repeater } from './repeater';
export { Link } from './link';
export { MediaToolbar } from './media-toolbar';
export { Image } from './image';
export { PostContext } from './post-context';
export { PostTitle } from './post-title';
export { PostFeaturedImage } from './post-featured-image';
export { PostMeta } from './post-meta';
export { PostExcerpt } from './post-excerpt';
export { PostAuthor } from './post-author';
export { PostDate, PostDatePicker } from './post-date';
export { PostTermList } from './post-term-list';
export { PostCategoryList } from './post-category-list';
export { PostPrimaryTerm } from './post-primary-term';
export { PostPrimaryCategory } from './post-primary-category';
export { RichTextCharacterLimit, getCharacterCount } from './rich-text-character-limit';
export { CircularProgressBar, Counter } from './counter';
74 changes: 74 additions & 0 deletions components/post-author/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Children } from '@wordpress/element';
import { store as coreStore } from '@wordpress/core-data';
import { Spinner } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import PropTypes from 'prop-types';
import { usePost } from '../../hooks';
import { Name, FirstName, LastName, Avatar, Bio, Email } from '../author';

import { AuthorContext } from '../author/context';

export const PostAuthor = (props) => {
const { children, ...rest } = props;
const { postId, postType } = usePost();

const [author, hasResolved] = useSelect(
(select) => {
const { getEditedEntityRecord, getUser, hasFinishedResolution } = select(coreStore);

const postQuery = ['postType', postType, postId];

const post = getEditedEntityRecord(...postQuery);
const hasResolvedPost = hasFinishedResolution('getEditedEntityRecord', postQuery);

const _authorId = hasResolvedPost ? post?.author : undefined;

const author = getUser(_authorId);
const hasResolvedAuthor = hasFinishedResolution('getUser', [_authorId]);

return [author, hasResolvedAuthor && hasResolvedPost];
},
[postType, postId],
);

const hasRenderCallback = typeof children === 'function';

const hasChildComponents = !hasRenderCallback && Children.count(children);

if (!hasResolved) {
return <Spinner />;
}

if (hasChildComponents) {
return (
<AuthorContext.Provider value={author}>
<div {...rest}>{children}</div>
</AuthorContext.Provider>
);
}

if (hasRenderCallback) {
return children(author);
}

return <Name {...rest} />;
};

PostAuthor.propTypes = {
children: PropTypes.oneOfType([
PropTypes.func,
PropTypes.node,
PropTypes.arrayOf(PropTypes.node),
]),
};

PostAuthor.defaultProps = {
children: null,
};

PostAuthor.Name = Name;
PostAuthor.FirstName = FirstName;
PostAuthor.LastName = LastName;
PostAuthor.Avatar = Avatar;
PostAuthor.Bio = Bio;
PostAuthor.Email = Email;
Loading