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

Fix: Refine Type Setup #333

Merged
merged 9 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use @ts-expect-error instead.

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
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
Loading