solve type errors

This commit is contained in:
Chuck Dries 2022-10-10 02:46:54 -07:00
parent b2afb0abfe
commit 18dad7cb0b
No known key found for this signature in database
GPG Key ID: A00B7AEAE1DC5BE6
10 changed files with 4526 additions and 49 deletions

View File

@ -19,8 +19,9 @@ module.exports = {
"plugin:react-hooks/recommended",
],
rules: {
"no-undef": 0,
"react/prop-types": 0,
"no-unused-vars": 1,
"no-unused-vars": 0,
"react/jsx-sort-props": 1,
},
};

View File

@ -21,6 +21,9 @@
"deploy": "yarn build && yarn upload",
"pretty": "prettier --write ."
},
"resolutions": {
"@types/react": "^17.0.38"
},
"dependencies": {
"@adobe/react-spectrum": "^3.19.0",
"@mdx-js/mdx": "^1.6.22",
@ -71,6 +74,7 @@
"@types/ramda": "^0.28.15",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@types/react-helmet": "^6.1.5",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"cross-env": "^7.0.3",

View File

@ -1,7 +1,12 @@
import * as React from "react";
import classNames from "classnames";
const KeywordsPicker = ({ keywords, value, onChange }) => {
interface KeywordsPickerProps {
keywords: string[];
value: string | null;
onChange: (val: string | null) => void;
}
const KeywordsPicker = ({ keywords, value, onChange }: KeywordsPickerProps) => {
return (
<div className="mx-2">
<span className="text-xs text-[#A2A2A2]">Collections</span>

View File

@ -1,6 +1,6 @@
import * as React from "react";
import { Link, Node } from "gatsby";
import { GatsbyImage, getImage, ImageDataLike } from "gatsby-plugin-image";
import { Link } from "gatsby";
import { GatsbyImage, getImage } from "gatsby-plugin-image";
import * as R from "ramda";
import { getAspectRatio, getName } from "../utils";
import useBreakpoint from "use-breakpoint";
@ -8,6 +8,7 @@ import useBreakpoint from "use-breakpoint";
// @ts-ignore
import themeBreakpoints from "../breakpoints";
import classNames from "classnames";
import { GalleryImage } from "../pages/photogallery";
interface Row {
aspect: number;
@ -16,7 +17,7 @@ interface Row {
}
interface MasonryGalleryProps {
images: (ImageDataLike & Node)[];
images: (GalleryImage)[];
aspectsByBreakpoint: {
[breakpoint: string]: number;
}
@ -40,9 +41,9 @@ const MasonryGallery = ({
const { breakpoint } = useBreakpoint(breakpoints, "sm");
const aspectRatios = React.useMemo(
() => R.map(getAspectRatio, images),
() => R.map(getAspectRatio, images).filter(Boolean),
[images]
);
) as number[];
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
const rows = React.useMemo(
@ -115,6 +116,7 @@ const MasonryGallery = ({
const widthNumber = ((ar / rowAspectRatioSum) * 100).toFixed(7);
width = `${widthNumber}%`;
}
// @ts-ignore
const img = getImage(image);
return (
<Link
@ -136,9 +138,9 @@ const MasonryGallery = ({
// borderColor: `rgb(${image.fields.imageMeta.vibrant.Vibrant.join(',')})`
borderColor: debugHue
? `hsl(
${image.fields.imageMeta.dominantHue[0]},
${image.fields.imageMeta.dominantHue[1] * 100}%,
${image.fields.imageMeta.dominantHue[2] * 100}%
${image.fields?.imageMeta?.dominantHue?.[0]},
${image.fields?.imageMeta?.dominantHue?.[1] ?? 0 * 100}%,
${image.fields?.imageMeta?.dominantHue?.[2] ?? 0 * 100}%
)`
: "black",
}}
@ -147,14 +149,14 @@ const MasonryGallery = ({
{debugHue && (
<span className="text-white z-20 absolute bg-black">
hsl(
{image.fields.imageMeta.dominantHue[0]},{" "}
{(image.fields.imageMeta.dominantHue[1] * 100).toFixed(2)}%,{" "}
{(image.fields.imageMeta.dominantHue[2] * 100).toFixed(2)}% )
{image.fields?.imageMeta?.dominantHue?.[0]},{" "}
{(image.fields?.imageMeta?.dominantHue?.[1] ?? 0 * 100).toFixed(2)}%,{" "}
{(image.fields?.imageMeta?.dominantHue?.[2] ?? 0 * 100).toFixed(2)}% )
</span>
)}
{debugRating && (
<span className="text-white z-20 absolute bg-black">
rating: {image.fields.imageMeta.meta.Rating}
rating: {image.fields?.imageMeta?.meta?.Rating}
</span>
)}
{img && (

View File

@ -5,7 +5,16 @@ import useDimensions from "react-cool-dimensions";
import Menu from "@spectrum-icons/workflow/Menu";
const Nav = ({ isClient, internalLinks, className }) => {
interface NavProps {
isClient?: boolean;
className?: string;
internalLinks: {
href: string;
label: string;
}[]
}
const Nav = ({ isClient, internalLinks, className }: NavProps) => {
const { observe, currentBreakpoint } = useDimensions({
breakpoints: { XS: 0, LG: 690 },
updateOnBreakpointChange: true,

4424
src/gatsby-types.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

4
src/global.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
/* eslint-disable */
declare interface Window {
plausible: any;
}

View File

@ -1,6 +1,6 @@
import * as React from "react";
import * as R from "ramda";
import { graphql } from "gatsby";
import { graphql, PageProps } from "gatsby";
import { Helmet } from "react-helmet";
import { Picker, Item } from "@adobe/react-spectrum";
@ -14,22 +14,25 @@ const SORT_KEYS = {
rating: ["fields", "imageMeta", "meta", "Rating"],
hue_debug: ["fields", "imageMeta", "dominantHue", 0],
date: [],
};
} as const;
const GalleryPage = ({ data }) => {
export type GalleryImage =
Queries.GalleryPageQueryQuery["allFile"]["nodes"][number];
const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
const hash =
typeof window !== "undefined" ? window.location.hash.replace("#", "") : "";
const [hashCleared, setHashCleared] = React.useState(false); // eslint-disable-line no-unused-vars
// ^ used just to force a re-render with the cleared hash value (I know, it's a smell for sure)
const [filterKeyword, _setKeyword] = React.useState(null);
const [sortKey, _setSortKey] = React.useState("rating");
const [filterKeyword, _setKeyword] = React.useState(null as string | null);
const [sortKey, _setSortKey] = React.useState("rating" as string);
const showDebug =
typeof window !== "undefined" &&
window.location.search.includes("debug=true");
const setKeyword = React.useCallback(
(newKeyword) => {
(newKeyword: string | null) => {
if (newKeyword) {
try {
window.plausible("Filter Keyword", {
@ -50,7 +53,7 @@ const GalleryPage = ({ data }) => {
);
const setSortKey = React.useCallback(
(newSortKey) => {
(newSortKey: string) => {
try {
window.plausible("Sort Gallery", {
props: { key: newSortKey },
@ -102,12 +105,12 @@ const GalleryPage = ({ data }) => {
const sortKeyFromUrl = url.searchParams.get("sort");
if (sortKeyFromUrl) {
_setSortKey(sortKeyFromUrl, false);
_setSortKey(sortKeyFromUrl);
}
const filterKeyFromUrl = url.searchParams.get("filter");
if (filterKeyFromUrl) {
_setKeyword(filterKeyFromUrl, false);
_setKeyword(filterKeyFromUrl);
}
// hacky but it works for now
@ -117,34 +120,41 @@ const GalleryPage = ({ data }) => {
}, 100);
}, [setSortKey, setKeyword, scrollIntoView]);
const images = React.useMemo(
const images: GalleryImage[] = React.useMemo(
() =>
R.pipe(
// @ts-ignore
sortKey === "date"
? R.sort((node1, node2) => {
? R.sort((node1: typeof data["allFile"]["nodes"][number], node2) => {
const date1 = new Date(
// @ts-ignore
R.path(["fields", "imageMeta", "dateTaken"], node1)
);
const date2 = new Date(
// @ts-ignore
R.path(["fields", "imageMeta", "dateTaken"], node2)
);
return -1 * (date1.getTime() - date2.getTime());
})
: R.sort(R.descend(R.path(SORT_KEYS[sortKey]))),
: // @ts-ignore
R.sort(R.descend(R.path(SORT_KEYS[sortKey]))),
filterKeyword
? R.filter((image) =>
// @ts-ignore
R.includes(
filterKeyword,
// @ts-ignore
R.path(["fields", "imageMeta", "meta", "Keywords"], image)
)
)
: R.identity
)(data.allFile.nodes),
)(data.allFile.nodes) as any,
[data, sortKey, filterKeyword]
);
return (
<>
{/* @ts-ignore */}
<Helmet>
<title>Photo Gallery | Chuck Dries</title>
<body className="bg-black text-white" />
@ -156,8 +166,7 @@ const GalleryPage = ({ data }) => {
{ href: "/", label: "Home" },
{ href: "/photogallery/", label: "Gallery" },
]}
>
</Nav>
></Nav>
<div className="flex flex-col md:flex-row md:items-end justify-between">
<h1 className="text-5xl mt-0 ml-5 mr-5 font-serif font-black z-10">
Photo Gallery
@ -182,13 +191,17 @@ const GalleryPage = ({ data }) => {
<div className="m-2">
<Picker
label="Sort by..."
// @ts-ignore
onSelectionChange={setSortKey}
selectedKey={sortKey}
>
<Item key="rating">Default</Item>
<Item key="date">Date</Item>
<Item key="hue">Hue</Item>
{showDebug && <Item key="hue_debug">Dominant hue[debug]</Item>}
<>{/* @ts-ignore */}</>
{showDebug ? (
<Item key="hue_debug">Dominant hue[debug]</Item>
) : undefined}
</Picker>
</div>
</div>

View File

@ -1,28 +1,30 @@
// import kebabCase from 'lodash/kebabCase';
export const getMeta = (image) => image.fields.imageMeta;
import { GalleryImage } from "./pages/photogallery";
export const getName = (image) =>
export const getMeta = (image: GalleryImage) => image.fields?.imageMeta;
export const getName = (image: GalleryImage) =>
getMeta(image)?.meta?.ObjectName || image.base;
// some pleasing default colors for SSR and initial hydration
export const getVibrant = (image) => getMeta(image)?.vibrant;
export const getVibrant = (image: GalleryImage) => getMeta(image)?.vibrant;
export const hasName = (image) => Boolean(getMeta(image)?.meta?.ObjectName);
export const hasName = (image: GalleryImage) => Boolean(getMeta(image)?.meta?.ObjectName);
export const getAspectRatio = (image) =>
image.childImageSharp.fluid.aspectRatio;
export const getAspectRatio = (image: GalleryImage): number =>
image.childImageSharp?.fluid?.aspectRatio ?? 1;
export const getCanonicalSize = (image) => ({
height: image.childImageSharp.gatsbyImageData.height,
width: image.childImageSharp.gatsbyImageData.width,
export const getCanonicalSize = (image: GalleryImage) => ({
height: image.childImageSharp?.gatsbyImageData.height,
width: image.childImageSharp?.gatsbyImageData.width,
});
export const getRgba = (palette, alpha) =>
export const getRgba = (palette: string[], alpha: number) =>
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
// work around SSR bug in react-helmet
export const getHelmetSafeBodyStyle = (vibrant, screenHeight?: number) => {
export const getHelmetSafeBodyStyle = (vibrant: Queries.FileFieldsImageMetaVibrant, screenHeight?: number) => {
const style = {
"--muted": vibrant.Muted,
"--dark-muted": vibrant.DarkMuted,
@ -36,11 +38,12 @@ export const getHelmetSafeBodyStyle = (vibrant, screenHeight?: number) => {
return style;
}
return Object.keys(style)
// @ts-ignore
.map((key) => `${key}: ${style[key]};`)
.join("");
};
const gcd = (a, b) => {
const gcd = (a: number, b: number): number => {
if (b < 0.0000001) {
return a; // Since there is a limited precision we need to limit the value.
}
@ -48,7 +51,7 @@ const gcd = (a, b) => {
return gcd(b, Math.floor(a % b)); // Discard any fractions due to limitations in precision.
};
export const getShutterFractionFromExposureTime = (exposureTime) => {
export const getShutterFractionFromExposureTime = (exposureTime: number) => {
if (exposureTime === 0.03333333333333333) {
return "1/30";
}
@ -80,7 +83,12 @@ export const getShutterFractionFromExposureTime = (exposureTime) => {
return `${numerator}/${denominator}`;
};
export const getGalleryPageUrl = ({ keyword, sortKey }, hash) => {
interface galleryPageUrlProps {
keyword: string | null;
sortKey: string;
}
export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => {
const url = new URL(
`${
typeof window !== "undefined"

View File

@ -4903,10 +4903,17 @@
dependencies:
"@types/react" "*"
"@types/react@*":
version "17.0.43"
resolved "https://registry.npmjs.org/@types/react/-/react-17.0.43.tgz"
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
"@types/react-helmet@^6.1.5":
version "6.1.5"
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-6.1.5.tgz#35f89a6b1646ee2bc342a33a9a6c8777933f9083"
integrity sha512-/ICuy7OHZxR0YCAZLNg9r7I9aijWUWvxaPR6uTuyxe8tAj5RL4Sw1+R6NhXUtOsarkGYPmaHdBDvuXh2DIN/uA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^17.0.38":
version "17.0.50"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.50.tgz#39abb4f7098f546cfcd6b51207c90c4295ee81fc"
integrity sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"