solve type errors
This commit is contained in:
		| @@ -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, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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> | ||||
| @@ -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 && ( | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										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
									
								
							
							
						
						
									
										4
									
								
								src/global.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| /* eslint-disable */ | ||||
| declare interface Window { | ||||
|   plausible: any; | ||||
| } | ||||
| @@ -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> | ||||
							
								
								
									
										36
									
								
								src/utils.ts
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								src/utils.ts
									
									
									
									
									
								
							| @@ -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" | ||||
|   | ||||
							
								
								
									
										15
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -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" "*" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user