From 38e6c112db1b50f78774a20de4bdd53b92a4dce6 Mon Sep 17 00:00:00 2001 From: Todd Schiller Date: Mon, 8 Jul 2024 14:06:55 -0400 Subject: [PATCH 1/3] Rename packageSearchModal --- .../{BrickIcon.tsx => PackageIcon.tsx} | 49 +++--- .../PackageDetail.tsx} | 35 +++-- .../PackageResult.tsx} | 30 ++-- .../PackageSearchModal.module.scss} | 0 .../PackageSearchModal.tsx} | 146 ++++++++++-------- .../QuickAdd.module.scss | 0 .../QuickAdd.tsx | 28 ++-- .../pages/integrations/IntegrationsPage.tsx | 6 +- .../integrations/PrivateIntegrationsCard.tsx | 4 +- .../referenceTab/PackageDetail.tsx | 7 +- .../referenceTab/PackageResult.tsx | 4 +- .../modals/addBrickModal/BrickDetail.tsx | 4 +- .../modals/addBrickModal/BrickGridItem.tsx | 4 +- .../editorNodeLayout/usePipelineNodes.tsx | 4 +- src/tsconfig.strictNullChecks.json | 6 +- 15 files changed, 179 insertions(+), 148 deletions(-) rename src/components/{BrickIcon.tsx => PackageIcon.tsx} (71%) rename src/components/{brickModalNoTags/BrickDetail.tsx => packageSearchModal/PackageDetail.tsx} (64%) rename src/components/{brickModalNoTags/BrickResult.tsx => packageSearchModal/PackageResult.tsx} (75%) rename src/components/{brickModalNoTags/BrickModal.module.scss => packageSearchModal/PackageSearchModal.module.scss} (100%) rename src/components/{brickModalNoTags/BrickModal.tsx => packageSearchModal/PackageSearchModal.tsx} (67%) rename src/components/{brickModalNoTags => packageSearchModal}/QuickAdd.module.scss (100%) rename src/components/{brickModalNoTags => packageSearchModal}/QuickAdd.tsx (66%) diff --git a/src/components/BrickIcon.tsx b/src/components/PackageIcon.tsx similarity index 71% rename from src/components/BrickIcon.tsx rename to src/components/PackageIcon.tsx index 06ba557d13..be6ef3a4e1 100644 --- a/src/components/BrickIcon.tsx +++ b/src/components/PackageIcon.tsx @@ -40,11 +40,11 @@ import useAsyncState from "@/hooks/useAsyncState"; import MarketplaceListingIcon from "@/components/MarketplaceListingIcon"; import { type Nullishable } from "@/utils/nullishUtils"; -function getDefaultBrickIcon( - brick: Instance, +function getDefaultPackageIcon( + packageInstance: Instance, brickType: Nullishable, ): IconProp { - if ("schema" in brick) { + if ("schema" in packageInstance) { return faCloud; } @@ -70,27 +70,35 @@ function getDefaultBrickIcon( } } - if (brick instanceof TriggerStarterBrickABC) { + if (packageInstance instanceof TriggerStarterBrickABC) { return faBolt; } - if (brick instanceof ButtonStarterBrickABC) { + if (packageInstance instanceof ButtonStarterBrickABC) { return faMousePointer; } - if (brick instanceof ContextMenuStarterBrickABC) { + if (packageInstance instanceof ContextMenuStarterBrickABC) { return faBars; } - if (brick instanceof SidebarStarterBrickABC) { + if (packageInstance instanceof SidebarStarterBrickABC) { return faColumns; } return faCube; } -type BrickIconProps = { - brick: T; +type PackageIconProps = { + /** + * A PackageInstance or Metadata object. Provide a PackageInstance instead of a Metadata to support brick type + * inference. + * + * @see PackageInstance + * @see Metadata + */ + packageOrMetadata: T; + size?: "1x" | "2x"; /** @@ -108,29 +116,32 @@ type BrickIconProps = { }; /** - * A package icon. Provide a PackageInstance instead of a Metadata to support type inference. + * A package icon. Provide a PackageInstance instead of a Metadata to support brick type inference. * - * WARNING: avoid rendering a lot of brick icons (20+) icons on a page at once. Each one waits for the marketplace + * WARNING: avoid rendering a lot of icons (20+) icons on a page at once. Each one waits for the marketplace * listing and searches all the listings. * * @see Metadata * @see PackageInstance */ -const BrickIcon = ({ - brick, +const PackageIcon = ({ + packageOrMetadata, size, faIconClass, inheritColor = false, -}: BrickIconProps) => { - const { data: type } = useAsyncState(async () => getType(brick), [brick]); +}: PackageIconProps) => { + const { data: type } = useAsyncState( + async () => getType(packageOrMetadata), + [packageOrMetadata], + ); const defaultIcon = useMemo( - () => getDefaultBrickIcon(brick, type), - [brick, type], + () => getDefaultPackageIcon(packageOrMetadata, type), + [packageOrMetadata, type], ); return ( ({ ); }; -export default BrickIcon; +export default PackageIcon; diff --git a/src/components/brickModalNoTags/BrickDetail.tsx b/src/components/packageSearchModal/PackageDetail.tsx similarity index 64% rename from src/components/brickModalNoTags/BrickDetail.tsx rename to src/components/packageSearchModal/PackageDetail.tsx index ae9a16c40f..32986a8e77 100644 --- a/src/components/brickModalNoTags/BrickDetail.tsx +++ b/src/components/packageSearchModal/PackageDetail.tsx @@ -1,34 +1,35 @@ import React from "react"; import { type MarketplaceListing } from "@/types/contract"; import { Button } from "react-bootstrap"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import SchemaTree from "@/components/schemaTree/SchemaTree"; import { type PackageInstance } from "@/types/registryTypes"; import { MARKETPLACE_URL } from "@/urlConstants"; -type BrickDetailProps = { - brick: T; +type PackageDetailProps = { + packageInstance: Instance; listing?: MarketplaceListing; onSelect: () => void; selectCaption: React.ReactNode; }; -const BrickDetail = ({ - brick, +const PackageDetail = ({ + packageInstance, selectCaption = "Select", listing, onSelect, -}: BrickDetailProps) => ( +}: PackageDetailProps) => ( ); -export default BrickDetail; +export default PackageDetail; diff --git a/src/components/brickModalNoTags/BrickResult.tsx b/src/components/packageSearchModal/PackageResult.tsx similarity index 75% rename from src/components/brickModalNoTags/BrickResult.tsx rename to src/components/packageSearchModal/PackageResult.tsx index d68d8c43b6..38e2a14f3d 100644 --- a/src/components/brickModalNoTags/BrickResult.tsx +++ b/src/components/packageSearchModal/PackageResult.tsx @@ -21,43 +21,47 @@ import cx from "classnames"; // TODO: Refactor to properly share styles across components (e.g. full component inheritance); // the "packageEditor/referenceTab/PackageResult" component probably doesn't expect to also affect a global component import styles from "@/extensionConsole/pages/packageEditor/referenceTab/PackageResult.module.scss"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { OfficialBadge } from "@/components/OfficialBadge"; import { type PackageInstance } from "@/types/registryTypes"; -type BrickResultProps = { - brick: T; +type PackageResultProps = { + packageInstance: Instance; onSelect: () => void; onShowDetail: () => void; active?: boolean; selectCaption: React.ReactNode; }; -const BrickResult = ({ - brick, +const PackageResult = ({ + packageInstance, onSelect, onShowDetail, selectCaption, active, -}: BrickResultProps) => ( +}: PackageResultProps) => (
- +
-
{brick.name}
- {brick.id} +
{packageInstance.name}
+ {packageInstance.id}

{/* Use a span if no description to ensure a consistent height for react-window */} - {brick.description ? `${brick.description}` :  } + {packageInstance.description ? ( + `${packageInstance.description}` + ) : ( +   + )}

- +
({ variant="primary" className="mb-1 text-nowrap" onClick={onSelect} - data-testid={`${brick.name} button`} + data-testid={`${packageInstance.name} button`} > {selectCaption} @@ -78,4 +82,4 @@ const BrickResult = ({ ); -export default BrickResult; +export default PackageResult; diff --git a/src/components/brickModalNoTags/BrickModal.module.scss b/src/components/packageSearchModal/PackageSearchModal.module.scss similarity index 100% rename from src/components/brickModalNoTags/BrickModal.module.scss rename to src/components/packageSearchModal/PackageSearchModal.module.scss diff --git a/src/components/brickModalNoTags/BrickModal.tsx b/src/components/packageSearchModal/PackageSearchModal.tsx similarity index 67% rename from src/components/brickModalNoTags/BrickModal.tsx rename to src/components/packageSearchModal/PackageSearchModal.tsx index 6fcd15581e..86c7273b4c 100644 --- a/src/components/brickModalNoTags/BrickModal.tsx +++ b/src/components/packageSearchModal/PackageSearchModal.tsx @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -import styles from "./BrickModal.module.scss"; +import styles from "./PackageSearchModal.module.scss"; import React, { type CSSProperties, @@ -37,9 +37,9 @@ import { useGetMarketplaceListingsQuery } from "@/data/service/api"; import Fuse from "fuse.js"; import { FixedSizeList as LazyList } from "react-window"; import AutoSizer, { type Size } from "react-virtualized-auto-sizer"; -import BrickResult from "./BrickResult"; -import BrickDetail from "./BrickDetail"; -import QuickAdd from "@/components/brickModalNoTags/QuickAdd"; +import PackageResult from "./PackageResult"; +import PackageDetail from "./PackageDetail"; +import QuickAdd from "./QuickAdd"; import { type Except } from "type-fest"; import cx from "classnames"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -51,56 +51,58 @@ import { isNullOrBlank } from "@/utils/stringUtils"; import useOnMountOnly from "@/hooks/useOnMountOnly"; import { freeze } from "@/utils/objectUtils"; -type BrickOption = { - data: T; +type PackageOption = { + data: Instance; value: RegistryId; label: string; }; -function makeBlockOption(brick: T): BrickOption { +function mapToPackageOption( + packageInstance: Instance, +): PackageOption { return { - value: brick.id, - label: brick.name, - data: brick, + value: packageInstance.id, + label: packageInstance.name, + data: packageInstance, }; } -function useSearch( - bricks: T[], +function useSearch( + packageInstances: Instance[], query: string, -): Array> { +): Array> { const [debouncedQuery] = useDebounce(query, 100, { trailing: true, leading: false, }); - const { fuse, brickOptions } = useMemo(() => { - const brickOptions = sortBy( + const { fuse, packageOptions } = useMemo(() => { + const packageOptions = sortBy( // We should never show @internal bricks to users. However, they'll sometimes find their way in from the registry - (bricks ?? []) + (packageInstances ?? []) .filter((x) => !x.id.startsWith("@internal/")) - .map((x) => makeBlockOption(x)), + .map((x) => mapToPackageOption(x)), (x) => x.label, ); - const fuse = new Fuse>(brickOptions, { + const fuse = new Fuse>(packageOptions, { keys: ["label", "data.id", "data.description"], }); - return { brickOptions, fuse }; - }, [bricks]); + return { packageOptions, fuse }; + }, [packageInstances]); return useMemo( () => isNullOrBlank(debouncedQuery) - ? brickOptions + ? packageOptions : fuse.search(debouncedQuery).map((x) => x.item), - [debouncedQuery, fuse, brickOptions], + [debouncedQuery, fuse, packageOptions], ); } -type ModalProps = { - bricks: T[]; - onSelect: (brick: T) => void; +type ModalProps = { + packageInstances: Instance[]; + onSelect: (packageInstance: Instance) => void; selectCaption?: React.ReactNode; recommendations?: RegistryId[]; close: () => void; @@ -112,47 +114,47 @@ type ButtonProps = { renderButton?: (onClick: () => void) => React.ReactNode; }; -type ItemType = { - searchResults: Array>; - setDetailBrick: (brick: T) => void; +type ItemType = { + searchResults: Array>; + setDetailPackage: (packageInstance: Instance) => void; selectCaption: React.ReactNode; - onSelect: (brick: T) => void; + onSelect: (brick: Instance) => void; close: () => void; - activeBrick: T | null; + activePackage: Instance | null; }; // The item renderer must be its own separate component to react-window from re-mounting the results // https://github.com/bvaughn/react-window/issues/420#issuecomment-585813335 -const ItemRenderer = ({ +const ItemRenderer = ({ index, style, data: { searchResults, - setDetailBrick, + setDetailPackage, selectCaption, onSelect, close, - activeBrick, + activePackage, }, }: { index: number; style: CSSProperties; - data: ItemType; + data: ItemType; }) => { - const { data: brick } = searchResults.at(index); + const { data: packageInstance } = searchResults.at(index); return (
- { - setDetailBrick(brick); + setDetailPackage(packageInstance); }} onSelect={() => { - onSelect(brick); + onSelect(packageInstance); close(); }} selectCaption={selectCaption} - active={activeBrick?.id === brick.id} + active={activePackage?.id === packageInstance.id} />
); @@ -160,16 +162,16 @@ const ItemRenderer = ({ // Need to provide a key because we reorder elements on search // See https://react-window.vercel.app/#/api/FixedSizeList -function itemKey( +function itemKey( index: number, - { searchResults }: ItemType, + { searchResults }: ItemType, ): RegistryId { // Find the item at the specified index. // In this case "data" is an Array that was passed to List as "itemData". const item = searchResults.at(index); // Return a value that uniquely identifies this item. - // Typically this will be a UID of some sort. + // Typically, this will be a UID of some sort. return item.value; } @@ -181,16 +183,16 @@ const defaultAddCaption = ( const DEFAULT_RECOMMENDATIONS = freeze([]); -function ActualModal({ - bricks, +function ActualModal({ + packageInstances, close, onSelect, selectCaption = defaultAddCaption, recommendations = DEFAULT_RECOMMENDATIONS, modalClassName, -}: ModalProps): React.ReactElement { +}: ModalProps): React.ReactElement { const [query, setQuery] = useState(""); - const [detailBrick, setDetailBrick] = useState(null); + const [detailPackage, setDetailPackage] = useState(null); const searchInput = useRef(null); // The react-window library requires exact height const brickResultSizePx = 87; @@ -200,24 +202,24 @@ function ActualModal({ const { data: listings = {} } = useGetMarketplaceListingsQuery(); - const searchResults = useSearch(bricks ?? [], query); + const searchResults = useSearch(packageInstances ?? [], query); - const recommendedBricks = useMemo(() => { + const recommendedPackages = useMemo(() => { if (recommendations.length === 0) { return; } // Retain the same order that the recommendations were passed in - const brickMap = new Map((bricks ?? []).map((brick) => [brick.id, brick])); + const packageMap = new Map((packageInstances ?? []).map((x) => [x.id, x])); return compact( - recommendations.map((registryId) => brickMap.get(registryId)), + recommendations.map((registryId) => packageMap.get(registryId)), ); - }, [recommendations, bricks]); + }, [recommendations, packageInstances]); useOnMountOnly(() => { // If there's no recommendations, default to the first brick so the right side isn't blank if (recommendations.length === 0 && searchResults.length > 0) { - setDetailBrick(searchResults[0].data); + setDetailPackage(searchResults[0].data); } }); @@ -258,12 +260,12 @@ function ActualModal({ itemData={ { searchResults, - setDetailBrick, - activeBrick: detailBrick, + setDetailPackage, + activePackage: detailPackage, selectCaption, onSelect, close, - } as ItemType + } as ItemType } > {ItemRenderer} @@ -272,23 +274,23 @@ function ActualModal({
- {detailBrick ? ( - { - onSelect(detailBrick); + onSelect(detailPackage); close(); }} /> ) : ( { - onSelect(brick); + onSelect={(packageInstance) => { + onSelect(packageInstance); close(); }} - recommendations={recommendedBricks} + recommendations={recommendedPackages} /> )} @@ -296,11 +298,19 @@ function ActualModal({ ); } -function BrickModal({ - caption = "Select a Brick", +/** + * A package search modal, without support for filtering by Marketplace tags. + * + * For the Page Editor brick modal, see `AddBrickModal`. + * + * @see AddBrickModal + */ +function PackageSearchModal({ + caption, renderButton, ...modalProps -}: Except, "close"> & ButtonProps): React.ReactElement { +}: Except, "close"> & + ButtonProps): React.ReactElement { const [show, setShow] = useState(false); const close = useCallback(() => { @@ -329,4 +339,4 @@ function BrickModal({ ); } -export default BrickModal; +export default PackageSearchModal; diff --git a/src/components/brickModalNoTags/QuickAdd.module.scss b/src/components/packageSearchModal/QuickAdd.module.scss similarity index 100% rename from src/components/brickModalNoTags/QuickAdd.module.scss rename to src/components/packageSearchModal/QuickAdd.module.scss diff --git a/src/components/brickModalNoTags/QuickAdd.tsx b/src/components/packageSearchModal/QuickAdd.tsx similarity index 66% rename from src/components/brickModalNoTags/QuickAdd.tsx rename to src/components/packageSearchModal/QuickAdd.tsx index 51ef55ddc5..6019f74c1c 100644 --- a/src/components/brickModalNoTags/QuickAdd.tsx +++ b/src/components/packageSearchModal/QuickAdd.tsx @@ -19,38 +19,40 @@ import styles from "./QuickAdd.module.scss"; import React from "react"; import { Card } from "react-bootstrap"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import cx from "classnames"; import { type PackageInstance } from "@/types/registryTypes"; -type OwnProps = { - onSelect: (block: T) => void; - recommendations: T[]; +type OwnProps = { + onSelect: (packageInstance: Instance) => void; + recommendations: Instance[]; }; -const QuickAdd = ({ +const QuickAdd = ({ recommendations, onSelect, -}: OwnProps) => ( +}: OwnProps) => (
-

Recommended Bricks

+

Recommended Packages

- {(recommendations ?? []).map((brick) => ( + {(recommendations ?? []).map((packageInstance) => ( { - onSelect(brick); + onSelect(packageInstance); }} >
- +
- {brick.name} - {brick.description} + {packageInstance.name} + + {packageInstance.description} +
))} diff --git a/src/extensionConsole/pages/integrations/IntegrationsPage.tsx b/src/extensionConsole/pages/integrations/IntegrationsPage.tsx index 841156df27..531d6e2249 100644 --- a/src/extensionConsole/pages/integrations/IntegrationsPage.tsx +++ b/src/extensionConsole/pages/integrations/IntegrationsPage.tsx @@ -31,7 +31,7 @@ import { services } from "@/background/messenger/api"; import ZapierIntegrationModal from "@/extensionConsole/pages/integrations/ZapierIntegrationModal"; import notify from "@/utils/notify"; import { useLocation } from "react-router"; -import BrickModal from "@/components/brickModalNoTags/BrickModal"; +import PackageSearchModal from "@/components/packageSearchModal/PackageSearchModal"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { isUUID, uuidv4 } from "@/types/helpers"; import useAuthorizationGrantFlow from "@/hooks/useAuthorizationGrantFlow"; @@ -421,9 +421,9 @@ const IntegrationsPage: React.VFC = () => { isPending={localState.isLoadingIntegrations} documentationUrl="https://docs.pixiebrix.com/integrations/configuring-integrations" toolbar={ - diff --git a/src/extensionConsole/pages/integrations/PrivateIntegrationsCard.tsx b/src/extensionConsole/pages/integrations/PrivateIntegrationsCard.tsx index 0e9af5f77d..e669c3edb9 100644 --- a/src/extensionConsole/pages/integrations/PrivateIntegrationsCard.tsx +++ b/src/extensionConsole/pages/integrations/PrivateIntegrationsCard.tsx @@ -27,7 +27,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { deleteCachedAuthData } from "@/background/messenger/api"; import notify from "@/utils/notify"; import EllipsisMenu from "@/components/ellipsisMenu/EllipsisMenu"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { type Integration, type IntegrationConfig, @@ -127,7 +127,7 @@ const columnFactory = ({ return ( <> - +
{value.name}
diff --git a/src/extensionConsole/pages/packageEditor/referenceTab/PackageDetail.tsx b/src/extensionConsole/pages/packageEditor/referenceTab/PackageDetail.tsx index 359c02f575..cead90f377 100644 --- a/src/extensionConsole/pages/packageEditor/referenceTab/PackageDetail.tsx +++ b/src/extensionConsole/pages/packageEditor/referenceTab/PackageDetail.tsx @@ -31,7 +31,7 @@ import useUserAction from "@/hooks/useUserAction"; import DetailSection from "./DetailSection"; import { type Schema } from "@/types/schemaTypes"; import { useGetMarketplaceListingsQuery } from "@/data/service/api"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { writeToClipboard } from "@/utils/clipboardUtils"; import { type PackageInstance } from "@/types/registryTypes"; import { MARKETPLACE_URL } from "@/urlConstants"; @@ -109,7 +109,10 @@ const PackageDetail = ({

{packageInstance.name}  - +

{packageInstance.id} diff --git a/src/extensionConsole/pages/packageEditor/referenceTab/PackageResult.tsx b/src/extensionConsole/pages/packageEditor/referenceTab/PackageResult.tsx index b270ffeed8..6a232581a7 100644 --- a/src/extensionConsole/pages/packageEditor/referenceTab/PackageResult.tsx +++ b/src/extensionConsole/pages/packageEditor/referenceTab/PackageResult.tsx @@ -21,7 +21,7 @@ import React, { useMemo } from "react"; import { ListGroup } from "react-bootstrap"; import cx from "classnames"; import { OfficialBadge } from "@/components/OfficialBadge"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { faEyeSlash, faGlobe, @@ -111,7 +111,7 @@ const PackageResult = ({ >

- +
diff --git a/src/pageEditor/modals/addBrickModal/BrickDetail.tsx b/src/pageEditor/modals/addBrickModal/BrickDetail.tsx index feb1fcbfac..b9971f12c5 100644 --- a/src/pageEditor/modals/addBrickModal/BrickDetail.tsx +++ b/src/pageEditor/modals/addBrickModal/BrickDetail.tsx @@ -2,7 +2,7 @@ import React from "react"; import { type Brick } from "@/types/brickTypes"; import { type MarketplaceListing } from "@/types/contract"; import { Button } from "react-bootstrap"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; import SchemaTree from "@/components/schemaTree/SchemaTree"; @@ -19,7 +19,7 @@ const BrickDetail: React.FunctionComponent<{

- {brick.name} + {brick.name}

{brick.id}

{brick.description}

diff --git a/src/pageEditor/modals/addBrickModal/BrickGridItem.tsx b/src/pageEditor/modals/addBrickModal/BrickGridItem.tsx index 8c4271d441..f41438fdf2 100644 --- a/src/pageEditor/modals/addBrickModal/BrickGridItem.tsx +++ b/src/pageEditor/modals/addBrickModal/BrickGridItem.tsx @@ -17,7 +17,7 @@ import React from "react"; import { Button } from "react-bootstrap"; -import BrickIcon from "@/components/BrickIcon"; +import PackageIcon from "@/components/PackageIcon"; import styles from "./BrickGridItem.module.scss"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -49,7 +49,7 @@ const BrickGridItem: React.VFC = ({ })} >
- + {brick.name} {brick.isPopular && ( , + icon: , runStatus: decideBlockStatus({ traceRecord, blockAnnotations, diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index a345ef7211..014bd11119 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -385,7 +385,7 @@ "./components/AsyncStateGate.test.tsx", "./components/AsyncStateGate.tsx", "./components/BlockFormSubmissionViaEnterIfFirstChild.tsx", - "./components/BrickIcon.tsx", + "./components/PackageIcon.tsx", "./components/Centered.tsx", "./components/ClickableElement.test.tsx", "./components/ClickableElement.tsx", @@ -429,8 +429,8 @@ "./components/asyncIcon.ts", "./components/banner/Banner.stories.tsx", "./components/banner/Banner.tsx", - "./components/brickModalNoTags/BrickResult.tsx", - "./components/brickModalNoTags/QuickAdd.tsx", + "./components/packageSearchModal/PackageResult.tsx", + "./components/packageSearchModal/QuickAdd.tsx", "./components/ellipsisMenu/EllipsisMenu.stories.tsx", "./components/ellipsisMenu/EllipsisMenu.tsx", "./components/errors/InputValidationErrorDetail.tsx", From b07043bf028a2c446c25c8feb3649b76d471d48e Mon Sep 17 00:00:00 2001 From: Todd Schiller Date: Mon, 8 Jul 2024 14:10:29 -0400 Subject: [PATCH 2/3] Explain type --- src/components/PackageIcon.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/PackageIcon.tsx b/src/components/PackageIcon.tsx index be6ef3a4e1..d206254c01 100644 --- a/src/components/PackageIcon.tsx +++ b/src/components/PackageIcon.tsx @@ -124,6 +124,8 @@ type PackageIconProps = { * @see Metadata * @see PackageInstance */ +// As of 2.0.5, the Metadata and PackageInstance types are currently equivalent. But include both in the union to make +// the type signature more explicit. const PackageIcon = ({ packageOrMetadata, size, From 08287984415386bb603b58c596b487583f00cfdd Mon Sep 17 00:00:00 2001 From: Todd Schiller Date: Tue, 9 Jul 2024 10:12:32 -0400 Subject: [PATCH 3/3] Remove uncessary generics --- src/components/PackageIcon.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/PackageIcon.tsx b/src/components/PackageIcon.tsx index d206254c01..590ec0c427 100644 --- a/src/components/PackageIcon.tsx +++ b/src/components/PackageIcon.tsx @@ -40,10 +40,11 @@ import useAsyncState from "@/hooks/useAsyncState"; import MarketplaceListingIcon from "@/components/MarketplaceListingIcon"; import { type Nullishable } from "@/utils/nullishUtils"; -function getDefaultPackageIcon( - packageInstance: Instance, +function getDefaultPackageIcon( + packageInstance: PackageInstance, brickType: Nullishable, ): IconProp { + // Is an integration definition. See Integration/IntegrationABC if ("schema" in packageInstance) { return faCloud; } @@ -89,7 +90,7 @@ function getDefaultPackageIcon( return faCube; } -type PackageIconProps = { +type PackageIconProps = { /** * A PackageInstance or Metadata object. Provide a PackageInstance instead of a Metadata to support brick type * inference. @@ -97,7 +98,7 @@ type PackageIconProps = { * @see PackageInstance * @see Metadata */ - packageOrMetadata: T; + packageOrMetadata: Metadata | PackageInstance; size?: "1x" | "2x"; @@ -126,12 +127,12 @@ type PackageIconProps = { */ // As of 2.0.5, the Metadata and PackageInstance types are currently equivalent. But include both in the union to make // the type signature more explicit. -const PackageIcon = ({ +const PackageIcon: React.FunctionComponent = ({ packageOrMetadata, size, faIconClass, inheritColor = false, -}: PackageIconProps) => { +}: PackageIconProps) => { const { data: type } = useAsyncState( async () => getType(packageOrMetadata), [packageOrMetadata],