Skip to content

Commit

Permalink
Merge pull request #333 from 10up/fix/update-custom-block-appender-to-ts
Browse files Browse the repository at this point in the history
Fix: Refine Type Setup
  • Loading branch information
fabiankaegy authored Jun 18, 2024
2 parents 87a622a + 3c2e581 commit 3934d98
Show file tree
Hide file tree
Showing 46 changed files with 29,137 additions and 28,708 deletions.
3 changes: 2 additions & 1 deletion components/author/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ export const LastName: React.FC<LastNameProps> = (props) => {
return <TagName {...rest}>{lastName}</TagName>;
};

function useDefaultAvatar() {
function useDefaultAvatar(): string {
const { avatarURL: defaultAvatarUrl } = useSelect((select) => {
// @ts-ignore-next-line The type definitions for the block editor store are incomplete.
const { getSettings } = select(blockEditorStore);
const { __experimentalDiscussionSettings } = getSettings();
return __experimentalDiscussionSettings;
Expand Down
2 changes: 1 addition & 1 deletion components/clipboard-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const ClipboardButton: React.FC<ClipboardButtonProps> = ({
const copied = labels.copied ? labels.copied : __('Copied');

useEffect(() => {
let timerId: undefined | number;
let timerId: ReturnType<typeof setTimeout>;

if (hasCopied) {
timerId = setTimeout(() => {
Expand Down
2 changes: 1 addition & 1 deletion components/color-settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface ColorSettingProps {
/**
* Callback called when a color is selected.
*/
onChange: Function;
onChange: (color: string) => void;
}

interface Color {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { Inserter } from '@wordpress/block-editor';
import { Button } from '@wordpress/components';
import { Button, IconType } from '@wordpress/components';
import { FC } from 'react';

/**
interface CustomBlockAppenderProps {
rootClientId: string;
className?: string;
buttonText?: string;
icon?: IconType;
[key: string]: any; // For additional props spread onto the Button component
}

/*
* CustomBlockAppender.
*
* Provide a Button component to trigger the inserter.
* Any undocumented props are spread onto the Button component.
*
* @param {object} props All props sent to this component.
* @param {string} props.rootClientId Client ID of the block where this is being used.
* @param {string} props.className class names to be added to the button.
* @param {string} [props.buttonText] Text to display in the Button.
* @param {string} [props.icon] The icon to use.
* @returns {Function} The component.
*/
const CustomBlockAppender = ({
export const CustomBlockAppender: FC<CustomBlockAppenderProps> = ({
rootClientId,
buttonText = '',
icon = 'plus',
Expand All @@ -25,7 +27,13 @@ const CustomBlockAppender = ({
<Inserter
isAppender
rootClientId={rootClientId}
renderToggle={({ onToggle, disabled }) => (
renderToggle={({
onToggle,
disabled,
}: {
onToggle: () => void;
disabled?: boolean;
}) => (
<Button
className={`tenup-${className}`}
onClick={onToggle}
Expand All @@ -39,5 +47,3 @@ const CustomBlockAppender = ({
/>
);
};

export { CustomBlockAppender };
9 changes: 1 addition & 8 deletions components/icon-picker/icon-picker-toolbar-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,7 @@ export const IconPickerToolbarButton: React.FC<IconPickerToolbarButtonProps> = (
placement: 'bottom-start',
}}
renderToggle={({ isOpen, onToggle }) => (
<ToolbarButton
onClick={onToggle}
aria-expanded={isOpen}
icon={buttonIcon}
placeholder={undefined}
onPointerEnterCapture={undefined}
onPointerLeaveCapture={undefined}
>
<ToolbarButton onClick={onToggle} aria-expanded={isOpen} icon={buttonIcon}>
{buttonLabel}
</ToolbarButton>
)}
Expand Down
1 change: 0 additions & 1 deletion components/icon-picker/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export const Icon: React.FC<IconProps> = forwardRef<HTMLDivElement, IconProps>(
const icon = useIcon(iconSet, name);

if (!icon || Array.isArray(icon)) {
// @ts-ignore -- Types on WP seem to require onPointerEnterCapture and onPointerLeaveCapture
return <Spinner />;
}

Expand Down
38 changes: 25 additions & 13 deletions components/image/index.js → components/image/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import { FC } from 'react';
import { MediaPlaceholder, InspectorControls } from '@wordpress/block-editor';
import { Spinner, FocalPointPicker, PanelBody, Placeholder } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

import { useMedia } from '../../hooks/use-media';

export const Image = (props) => {
const {
id,
size = 'full',
onSelect,
focalPoint = { x: 0.5, y: 0.5 },
onChangeFocalPoint = undefined,
labels = {},
canEditImage = true,
allowedTypes = ['image'],
...rest
} = props;
interface ImageProps {
id: number;
size?: string;
onSelect: (media: any) => void; // Define a more specific type for media if possible
focalPoint?: { x: number; y: number };
onChangeFocalPoint?: (focalPoint: { x: number; y: number }) => void;
labels?: { [key: string]: string };
canEditImage?: boolean;
allowedTypes?: string[];
[key: string]: any; // For additional props spread onto the img element
}

export const Image: FC<ImageProps> = ({
id,
size = 'full',
onSelect,
focalPoint = { x: 0.5, y: 0.5 },
onChangeFocalPoint = undefined,
labels = {},
canEditImage = true,
allowedTypes = ['image'],
...rest
}) => {
const hasImage = !!id;
const { media, isResolvingMedia } = useMedia(id);

Expand All @@ -40,7 +52,7 @@ export const Image = (props) => {
if (isResolvingMedia) {
return <Spinner />;
}

// @ts-ignore-next-line - The media object is not typed by WordPress currently
const imageUrl = media?.media_details?.sizes?.[size]?.source_url ?? media?.source_url;
const altText = media?.alt_text;

Expand Down
5 changes: 3 additions & 2 deletions components/is-admin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useSelect } from '@wordpress/data';
import { store as coreStore } from '@wordpress/core-data';

interface IsAdminProps {
/**
Expand All @@ -20,8 +21,8 @@ interface IsAdminProps {
* fallback component via the fallback prop.
*/
export const IsAdmin: React.FC<IsAdminProps> = ({ fallback = null, children }) => {
const hasAdminPermissions: boolean = useSelect(
(select) => select('core').canUser('read', 'users?roles=1'),
const hasAdminPermissions = useSelect(
(select) => select(coreStore).canUser('read', 'users?roles=1'),
[],
);
return hasAdminPermissions ? children : fallback;
Expand Down
60 changes: 35 additions & 25 deletions components/link/index.js → components/link/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import styled from '@emotion/styled';
*/
import { __ } from '@wordpress/i18n';
import { useState, useEffect, useRef } from '@wordpress/element';
import { FC } from 'react';
import { Popover, Icon, Tooltip } from '@wordpress/components';
// @ts-ignore-next-line - The type definitions for the block editor are missing the __experimentalLinkControl import.
import { __experimentalLinkControl as LinkControl, RichText } from '@wordpress/block-editor';

/**
Expand All @@ -18,15 +20,16 @@ import { __experimentalLinkControl as LinkControl, RichText } from '@wordpress/b
import { StyledComponentContext } from '../styled-components-context';
import { useOnClickOutside } from '../../hooks/use-on-click-outside';

/**
interface SuggestionsQuery {
type?: string;
subtype?: string;
}

/*
* Given the Link block's type attribute, return the query params to give to
* /wp/v2/search.
*
* @param {string} type Link block's type attribute.
* @param {string} kind Link block's entity of kind (post-type|taxonomy)
* @returns {{ type?: string, subtype?: string }} Search query params.
*/
function getSuggestionsQuery(type, kind) {
function getSuggestionsQuery(type: string, kind: string): SuggestionsQuery {
switch (type) {
case 'post':
case 'page':
Expand Down Expand Up @@ -84,30 +87,35 @@ const StylesRichTextLink = styled(RichText)`
}
`;

/**
interface NewLinkProps {
url?: string;
opensInNewTab?: boolean;
title?: string;
}

interface LinkProps {
value?: string;
type?: string;
opensInNewTab?: boolean;
url?: string;
onLinkChange: (value: NewLinkProps) => void;
onTextChange: (text: string) => void;
onLinkRemove?: () => void;
kind?: string;
placeholder?: string;
className?: string;
}

/*
* Link component that can be used inside other Gutenberg blocks for setting up URLs.
*
* The link should not be visible if the block is not focused. This will maintain nicer
* visuals in the block editor as a whole.
*
* @param {...object} props All properties passed to the component.
* @param {string} props.value The text to show inside the link
* @param {string} props.type Post or Page, used to autosuggest content for URL
* @param {boolean} props.opensInNewTab Should the link open in a new tab?
* @param {string} props.url The actual link to be set as href
* @param {Function} props.onLinkChange Callback when the URL is changed
* @param {Function} props.onLinkRemove Callback when the URL is changed
* @param {Function} props.onTextChange Callback when the link's text is changed
* @param {string} props.kind Page or Post
* @param {string} props.placeholder Text visible before actual value is inserted
* @param {string} props.className html class to be applied to the anchor element
*
* @returns {*} The rendered component.
*/
export const Link = ({
value = undefined,
export const Link: FC<LinkProps> = ({
value = '',
type = '',
opensInNewTab,
opensInNewTab = false,
url = undefined,
onLinkChange,
onTextChange,
Expand All @@ -122,7 +130,7 @@ export const Link = ({
const openPopover = () => setIsPopoverVisible(true);
const closePopover = () => setIsPopoverVisible(false);

const linkRef = useRef();
const linkRef = useRef<HTMLAnchorElement>(null);
const popoverRef = useOnClickOutside(closePopover);

const link = {
Expand Down Expand Up @@ -152,6 +160,7 @@ export const Link = ({
__unstablePastePlainText
allowedFormats={[]}
onClick={openPopover}
// @ts-ignore-next-line - The ref is not typed correctly in the RichText component.
ref={linkRef}
{...rest}
/>
Expand All @@ -173,6 +182,7 @@ export const Link = ({

{isPopoverVisible && (
<Popover
// @ts-ignore-next-line - In order to support older versions of Gutenberg, we need to pass the anchorRef prop.
anchorRef={linkRef.current}
anchor={linkRef.current}
ref={popoverRef}
Expand Down
3 changes: 2 additions & 1 deletion components/media-toolbar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { __ } from '@wordpress/i18n';
// @ts-ignore-next-line - The types for this package are incorrect.
import { MediaReplaceFlow, MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
import type { Attachment } from '@wordpress/core-data';
Expand Down Expand Up @@ -44,7 +45,7 @@ export const MediaToolbar: React.FC<MediaToolbarProps> = ({
const { media } = useMedia(id);

return (
<ToolbarGroup label={__('Media', '10up-block-components')}>
<ToolbarGroup>
{hasImage ? (
<>
<MediaReplaceFlow
Expand Down
1 change: 1 addition & 0 deletions components/optional/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-ignore-next-line - The WordPress types are missing the hasFinishedResolution method.
import { useBlockEditContext } from '@wordpress/block-editor';

interface OptionalProps {
Expand Down
2 changes: 2 additions & 0 deletions components/post-author/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ export const PostAuthor: React.FC<PostAuthorProps> & {

const [author, hasResolved] = useSelect(
(select) => {
// @ts-ignore-next-line - The type definitions for the core store are incomplete.
const { getEditedEntityRecord, getUser, hasFinishedResolution } = select(coreStore);

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

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

// @ts-ignore-next-line - The type definitions for the core store are incomplete.
const _authorId = hasResolvedPost ? post?.author : undefined;

const author = getUser(_authorId);
Expand Down
File renamed without changes.
13 changes: 0 additions & 13 deletions components/post-context/context.js

This file was deleted.

30 changes: 30 additions & 0 deletions components/post-context/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createContext, useContext } from '@wordpress/element';

interface PostContextProps {
/**
* The ID of the post.
*/
postId?: number;

/**
* The type of the post.
*/
postType?: string;

/**
* Whether the post is editable.
*/
isEditable?: boolean;
}

export const DEFAULT_POST_CONTEXT = {
postId: undefined,
postType: undefined,
isEditable: undefined,
};

export const PostContext = createContext<PostContextProps>(DEFAULT_POST_CONTEXT);

export const usePostContext = () => {
return useContext(PostContext);
};
17 changes: 0 additions & 17 deletions components/post-context/index.js

This file was deleted.

Loading

0 comments on commit 3934d98

Please sign in to comment.