Compare commits
No commits in common. "main" and "5ddaf606c1ba8afc81516f72c7a5170489c691ff" have entirely different histories.
main
...
5ddaf606c1
@ -1,2 +0,0 @@
|
|||||||
[lfs]
|
|
||||||
url = "https://git.chuckdries.com/chuckdries/Personal-Website.git/info/lfs/"
|
|
Binary file not shown.
Binary file not shown.
BIN
data/gallery/DSC00003.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC00003.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC00015.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC00015.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC00159-2.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC00159-2.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC00512.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC00512.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC01832.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC01832.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC02538-2.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC02538-2.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC03049.jpg
(Stored with Git LFS)
Normal file
BIN
data/gallery/DSC03049.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
data/gallery/DSC03401.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC03401.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC04122.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC04122.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC05702.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC05702.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC06124.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC06124.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC06515.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC06515.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC06719.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC06719.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC06803.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC06803.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC08086.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC08086.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC08103.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC08103.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC08222.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC08222.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC08263.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC08263.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC08588.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC08588.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC09447.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC09447.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC09453.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC09453.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/DSC09454.jpg
(Stored with Git LFS)
BIN
data/gallery/DSC09454.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/_DSC6060.jpg
(Stored with Git LFS)
BIN
data/gallery/_DSC6060.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/_DSC6062.jpg
(Stored with Git LFS)
BIN
data/gallery/_DSC6062.jpg
(Stored with Git LFS)
Binary file not shown.
BIN
data/gallery/_DSC6066.jpg
(Stored with Git LFS)
BIN
data/gallery/_DSC6066.jpg
(Stored with Git LFS)
Binary file not shown.
@ -14,25 +14,6 @@ export const onRouteUpdate = function () {
|
|||||||
window.plausible("pageview");
|
window.plausible("pageview");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// docs say you can return a scroll position from this fn, but that's a bold-faced lie
|
|
||||||
export const shouldUpdateScroll = ({
|
|
||||||
prevRouterProps,
|
|
||||||
routerProps: { location },
|
|
||||||
pathname,
|
|
||||||
}) => {
|
|
||||||
if (pathname.startsWith('/photogallery/') && pathname !== '/photogallery/' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (prevRouterProps?.location.pathname === pathname) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pathname === "/photogallery/" && location.hash.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// import * as React from 'react';
|
// import * as React from 'react';
|
||||||
// import { MDXProvider } from '@mdx-js/react';
|
// import { MDXProvider } from '@mdx-js/react';
|
||||||
|
|
||||||
|
@ -10,10 +10,6 @@ import sharp from "sharp";
|
|||||||
import { Palette } from "node-vibrant/lib/color";
|
import { Palette } from "node-vibrant/lib/color";
|
||||||
import { performance } from "perf_hooks";
|
import { performance } from "perf_hooks";
|
||||||
|
|
||||||
import util from "node:util";
|
|
||||||
import { exec as _exec } from "child_process";
|
|
||||||
const exec = util.promisify(_exec);
|
|
||||||
|
|
||||||
// const path = require("path");
|
// const path = require("path");
|
||||||
// const Vibrant = require("node-vibrant");
|
// const Vibrant = require("node-vibrant");
|
||||||
// const chroma = require("chroma-js");
|
// const chroma = require("chroma-js");
|
||||||
@ -118,8 +114,7 @@ function transformMetaToNodeData(
|
|||||||
metaData: Record<string, unknown>,
|
metaData: Record<string, unknown>,
|
||||||
vibrantData: Palette,
|
vibrantData: Palette,
|
||||||
imagePath: string,
|
imagePath: string,
|
||||||
{ r, g, b }: { r: number; b: number; g: number },
|
{ r, g, b }: { r: number; b: number; g: number }
|
||||||
datePublished: string
|
|
||||||
) {
|
) {
|
||||||
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
const vibrant = vibrantData ? processColors(vibrantData, imagePath) : null;
|
||||||
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
const vibrantHue = vibrantData.Vibrant!.getHsl()[0] * 360;
|
||||||
@ -136,7 +131,6 @@ function transformMetaToNodeData(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
dateTaken: metaData.DateTimeOriginal,
|
dateTaken: metaData.DateTimeOriginal,
|
||||||
datePublished,
|
|
||||||
meta: {
|
meta: {
|
||||||
Make: metaData.Make,
|
Make: metaData.Make,
|
||||||
Model: metaData.Model,
|
Model: metaData.Model,
|
||||||
@ -145,7 +139,6 @@ function transformMetaToNodeData(
|
|||||||
ISO: metaData.ISO,
|
ISO: metaData.ISO,
|
||||||
DateTimeOriginal: metaData.DateTimeOriginal,
|
DateTimeOriginal: metaData.DateTimeOriginal,
|
||||||
CreateDate: metaData.CreateDate,
|
CreateDate: metaData.CreateDate,
|
||||||
ModifyDate: metaData.ModifyDate,
|
|
||||||
ShutterSpeedValue: metaData.ShutterSpeedValue,
|
ShutterSpeedValue: metaData.ShutterSpeedValue,
|
||||||
ApertureValue: metaData.ApertureValue,
|
ApertureValue: metaData.ApertureValue,
|
||||||
FocalLength: metaData.FocalLength,
|
FocalLength: metaData.FocalLength,
|
||||||
@ -180,34 +173,13 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
const { createNodeField } = actions;
|
const { createNodeField } = actions;
|
||||||
|
|
||||||
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
if (node.internal.type === "File" && node.sourceInstanceName === "gallery") {
|
||||||
const { stdout: datePublished, stderr } = await exec(
|
const metaData = await exifr.parse(node.absolutePath as string, {
|
||||||
`git log --diff-filter=A --follow --format=%aI -1 -- ${node.absolutePath}`
|
iptc: true,
|
||||||
);
|
xmp: true,
|
||||||
|
// icc: true
|
||||||
|
});
|
||||||
|
|
||||||
if (stderr.length) {
|
const sharpImage = sharp(node.absolutePath as string);
|
||||||
console.error("something went wrong checking publish date: ", stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
let metaData;
|
|
||||||
try {
|
|
||||||
metaData = await exifr.parse(node.absolutePath as string, {
|
|
||||||
iptc: true,
|
|
||||||
xmp: true,
|
|
||||||
// icc: true
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`something wen wrong with exifr on image ${node.base}`, e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sharpImage: sharp.Sharp;
|
|
||||||
|
|
||||||
try {
|
|
||||||
sharpImage = sharp(node.absolutePath as string);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(`something wen wrong with sharp on image ${node.base}`, e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
const { dominant } = await sharpImage.stats();
|
const { dominant } = await sharpImage.stats();
|
||||||
const resizedImage = await sharpImage
|
const resizedImage = await sharpImage
|
||||||
.resize({
|
.resize({
|
||||||
@ -228,9 +200,7 @@ export const onCreateNode: GatsbyNode["onCreateNode"] = async function ({
|
|||||||
metaData,
|
metaData,
|
||||||
vibrantData,
|
vibrantData,
|
||||||
node.absolutePath as string,
|
node.absolutePath as string,
|
||||||
dominant,
|
dominant
|
||||||
// if datePublished is empty, image has not been committed to git yet and is thus brand new
|
|
||||||
datePublished.length ? datePublished.replace("\n", "") : new Date().toISOString()
|
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
"gatsby-source-filesystem": "^5.0.0",
|
"gatsby-source-filesystem": "^5.0.0",
|
||||||
"gatsby-transformer-sharp": "^5.0.0",
|
"gatsby-transformer-sharp": "^5.0.0",
|
||||||
"kebab-case": "^1.0.1",
|
"kebab-case": "^1.0.1",
|
||||||
"lodash.debounce": "^4.0.8",
|
|
||||||
"node-iptc": "^1.0.5",
|
"node-iptc": "^1.0.5",
|
||||||
"node-vibrant": "3.1.6",
|
"node-vibrant": "3.1.6",
|
||||||
"postcss": "^8.4.19",
|
"postcss": "^8.4.19",
|
||||||
@ -61,7 +60,6 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chroma-js": "^2.1.4",
|
"@types/chroma-js": "^2.1.4",
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
|
||||||
"@types/node": "^18.8.3",
|
"@types/node": "^18.8.3",
|
||||||
"@types/ramda": "^0.28.15",
|
"@types/ramda": "^0.28.15",
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.0.21",
|
||||||
|
193
scratchpad.js
193
scratchpad.js
@ -1,193 +0,0 @@
|
|||||||
a = {
|
|
||||||
ApplicationRecordVersion: '\x00\x04',
|
|
||||||
DateCreated: '2015-10-18T17:59:38',
|
|
||||||
TimeCreated: '175938',
|
|
||||||
DigitalCreationDate: '20151018',
|
|
||||||
DigitalCreationTime: '175938',
|
|
||||||
format: 'image/jpeg',
|
|
||||||
CreatorTool: 'Adobe Lightroom 5.4 (Macintosh)',
|
|
||||||
ModifyDate: '2022-07-09T21:16:39.000Z',
|
|
||||||
CreateDate: '2015-10-19T00:59:38.000Z',
|
|
||||||
MetadataDate: '2022-07-09T14:16:39-07:00',
|
|
||||||
Rating: 5,
|
|
||||||
LensInfo: [ 50, 50, 1.8, 1.8 ],
|
|
||||||
Lens: 'DT 50mm F1.8 SAM',
|
|
||||||
DocumentID: 'xmp.did:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
|
||||||
OriginalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
|
||||||
InstanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
|
||||||
History: [
|
|
||||||
{ action: 'derived', parameters: 'saved to new location' },
|
|
||||||
{
|
|
||||||
action: 'saved',
|
|
||||||
instanceID: 'xmp.iid:27795bf1-8bb2-49a0-807a-cf6150bd505b',
|
|
||||||
when: '2022-07-09T14:16:39-07:00',
|
|
||||||
softwareAgent: 'Adobe Lightroom 5.4 (Macintosh)',
|
|
||||||
changed: '/'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
DerivedFrom: {
|
|
||||||
documentID: 'CE2B8F240393ADFDF9F092CF395C6632',
|
|
||||||
originalDocumentID: 'CE2B8F240393ADFDF9F092CF395C6632'
|
|
||||||
},
|
|
||||||
good: true,
|
|
||||||
Version: 14.4,
|
|
||||||
ProcessVersion: 6.7,
|
|
||||||
WhiteBalance: 'Manual',
|
|
||||||
IncrementalTemperature: -11,
|
|
||||||
IncrementalTint: 23,
|
|
||||||
Exposure2012: 0,
|
|
||||||
Contrast2012: 6,
|
|
||||||
Highlights2012: 0,
|
|
||||||
Shadows2012: 0,
|
|
||||||
Whites2012: 35,
|
|
||||||
Blacks2012: -22,
|
|
||||||
Texture: 0,
|
|
||||||
Clarity2012: 0,
|
|
||||||
Dehaze: 0,
|
|
||||||
Vibrance: 0,
|
|
||||||
Saturation: 'Normal',
|
|
||||||
ParametricShadows: 0,
|
|
||||||
ParametricDarks: 0,
|
|
||||||
ParametricLights: 0,
|
|
||||||
ParametricHighlights: 0,
|
|
||||||
ParametricShadowSplit: 25,
|
|
||||||
ParametricMidtoneSplit: 50,
|
|
||||||
ParametricHighlightSplit: 75,
|
|
||||||
Sharpness: 'Normal',
|
|
||||||
LuminanceSmoothing: 0,
|
|
||||||
ColorNoiseReduction: 0,
|
|
||||||
HueAdjustmentRed: 0,
|
|
||||||
HueAdjustmentOrange: 0,
|
|
||||||
HueAdjustmentYellow: 0,
|
|
||||||
HueAdjustmentGreen: 0,
|
|
||||||
HueAdjustmentAqua: 0,
|
|
||||||
HueAdjustmentBlue: 0,
|
|
||||||
HueAdjustmentPurple: 0,
|
|
||||||
HueAdjustmentMagenta: 0,
|
|
||||||
SaturationAdjustmentRed: 0,
|
|
||||||
SaturationAdjustmentOrange: 0,
|
|
||||||
SaturationAdjustmentYellow: 0,
|
|
||||||
SaturationAdjustmentGreen: 0,
|
|
||||||
SaturationAdjustmentAqua: 0,
|
|
||||||
SaturationAdjustmentBlue: 0,
|
|
||||||
SaturationAdjustmentPurple: 0,
|
|
||||||
SaturationAdjustmentMagenta: 0,
|
|
||||||
LuminanceAdjustmentRed: 0,
|
|
||||||
LuminanceAdjustmentOrange: 0,
|
|
||||||
LuminanceAdjustmentYellow: 0,
|
|
||||||
LuminanceAdjustmentGreen: 0,
|
|
||||||
LuminanceAdjustmentAqua: 0,
|
|
||||||
LuminanceAdjustmentBlue: 0,
|
|
||||||
LuminanceAdjustmentPurple: 0,
|
|
||||||
LuminanceAdjustmentMagenta: 0,
|
|
||||||
SplitToningShadowHue: 0,
|
|
||||||
SplitToningShadowSaturation: 0,
|
|
||||||
SplitToningHighlightHue: 0,
|
|
||||||
SplitToningHighlightSaturation: 0,
|
|
||||||
SplitToningBalance: 0,
|
|
||||||
ColorGradeMidtoneHue: 0,
|
|
||||||
ColorGradeMidtoneSat: 0,
|
|
||||||
ColorGradeShadowLum: 0,
|
|
||||||
ColorGradeMidtoneLum: 0,
|
|
||||||
ColorGradeHighlightLum: 0,
|
|
||||||
ColorGradeBlending: 50,
|
|
||||||
ColorGradeGlobalHue: 0,
|
|
||||||
ColorGradeGlobalSat: 0,
|
|
||||||
ColorGradeGlobalLum: 0,
|
|
||||||
AutoLateralCA: 0,
|
|
||||||
LensProfileEnable: 0,
|
|
||||||
LensManualDistortionAmount: 0,
|
|
||||||
VignetteAmount: 0,
|
|
||||||
DefringePurpleAmount: 0,
|
|
||||||
DefringePurpleHueLo: 30,
|
|
||||||
DefringePurpleHueHi: 70,
|
|
||||||
DefringeGreenAmount: 0,
|
|
||||||
DefringeGreenHueLo: 40,
|
|
||||||
DefringeGreenHueHi: 60,
|
|
||||||
PerspectiveUpright: 0,
|
|
||||||
PerspectiveVertical: 0,
|
|
||||||
PerspectiveHorizontal: 0,
|
|
||||||
PerspectiveRotate: 0,
|
|
||||||
PerspectiveAspect: 0,
|
|
||||||
PerspectiveScale: 100,
|
|
||||||
PerspectiveX: 0,
|
|
||||||
PerspectiveY: 0,
|
|
||||||
GrainAmount: 0,
|
|
||||||
PostCropVignetteAmount: 0,
|
|
||||||
ShadowTint: 0,
|
|
||||||
RedHue: 0,
|
|
||||||
RedSaturation: 0,
|
|
||||||
GreenHue: 0,
|
|
||||||
GreenSaturation: 0,
|
|
||||||
BlueHue: 0,
|
|
||||||
BlueSaturation: 0,
|
|
||||||
ConvertToGrayscale: false,
|
|
||||||
OverrideLookVignette: false,
|
|
||||||
ToneCurveName2012: 'Linear',
|
|
||||||
CameraProfile: 'Embedded',
|
|
||||||
CameraProfileDigest: '54650A341B5B5CCAE8442D0B43A92BCE',
|
|
||||||
HasSettings: true,
|
|
||||||
CropTop: 0,
|
|
||||||
CropLeft: 0,
|
|
||||||
CropBottom: 1,
|
|
||||||
CropRight: 1,
|
|
||||||
CropAngle: 0,
|
|
||||||
CropConstrainToWarp: 0,
|
|
||||||
HasCrop: false,
|
|
||||||
AlreadyApplied: true,
|
|
||||||
ToneCurvePV2012: [ '0, 0', '255, 255' ],
|
|
||||||
ToneCurvePV2012Red: [ '0, 0', '255, 255' ],
|
|
||||||
ToneCurvePV2012Green: [ '0, 0', '255, 255' ],
|
|
||||||
ToneCurvePV2012Blue: [ '0, 0', '255, 255' ],
|
|
||||||
Make: 'SONY',
|
|
||||||
Model: 'SLT-A55V',
|
|
||||||
XResolution: 240,
|
|
||||||
YResolution: 240,
|
|
||||||
ResolutionUnit: 'inches',
|
|
||||||
Software: 'Adobe Lightroom 5.4 (Macintosh)',
|
|
||||||
ExposureTime: 0.01,
|
|
||||||
FNumber: 1.8,
|
|
||||||
ExposureProgram: 'Manual',
|
|
||||||
ISO: 200,
|
|
||||||
SensitivityType: 2,
|
|
||||||
RecommendedExposureIndex: 200,
|
|
||||||
ExifVersion: '2.3.1',
|
|
||||||
DateTimeOriginal: '2015-10-19T00:59:38.000Z',
|
|
||||||
OffsetTime: '-07:00',
|
|
||||||
ShutterSpeedValue: 6.643856,
|
|
||||||
ApertureValue: 1.695994,
|
|
||||||
BrightnessValue: 3,
|
|
||||||
ExposureCompensation: 0,
|
|
||||||
MaxApertureValue: 1.7,
|
|
||||||
MeteringMode: 'Pattern',
|
|
||||||
LightSource: 'Cloudy weather',
|
|
||||||
Flash: 'Flash did not fire, compulsory flash mode',
|
|
||||||
FocalLength: 50,
|
|
||||||
ColorSpace: 1,
|
|
||||||
FileSource: 'Digital Camera',
|
|
||||||
SceneType: 'Directly photographed',
|
|
||||||
CustomRendered: 'Normal',
|
|
||||||
ExposureMode: 'Manual',
|
|
||||||
FocalLengthIn35mmFormat: 75,
|
|
||||||
SceneCaptureType: 'Standard',
|
|
||||||
Contrast: 'Normal',
|
|
||||||
LensModel: 'DT 50mm F1.8 SAM',
|
|
||||||
GPSVersionID: '2.2.0.0',
|
|
||||||
GPSLatitudeRef: 'N',
|
|
||||||
GPSLatitude: [ 33, 25.7121, 0 ],
|
|
||||||
GPSLongitudeRef: 'W',
|
|
||||||
GPSLongitude: [ 111, 55.57122, 0 ],
|
|
||||||
GPSAltitude: 354.7,
|
|
||||||
GPSTimeStamp: '19:2:7',
|
|
||||||
GPSStatus: 'V',
|
|
||||||
GPSMeasureMode: '3',
|
|
||||||
GPSSpeedRef: 'K',
|
|
||||||
GPSSpeed: 33.8,
|
|
||||||
GPSTrackRef: 'T',
|
|
||||||
GPSTrack: 0.36,
|
|
||||||
GPSMapDatum: 'WGS-84',
|
|
||||||
GPSDateStamp: '2015:10:09',
|
|
||||||
GPSDifferential: 0,
|
|
||||||
latitude: 33.428535,
|
|
||||||
longitude: -111.926187
|
|
||||||
}
|
|
@ -63,15 +63,6 @@ const GalleryImage = ({ data, location: { state } }) => {
|
|||||||
setIsClient(true);
|
setIsClient(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
window.scrollTo({
|
|
||||||
top: 180,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
}, 50);
|
|
||||||
}, [image.base]);
|
|
||||||
|
|
||||||
const nextIndex =
|
const nextIndex =
|
||||||
sortedImageList && currentIndex < sortedImageList.length
|
sortedImageList && currentIndex < sortedImageList.length
|
||||||
? currentIndex + 1
|
? currentIndex + 1
|
||||||
@ -144,7 +135,7 @@ const GalleryImage = ({ data, location: { state } }) => {
|
|||||||
locationString = location.join(", ");
|
locationString = location.join(", ");
|
||||||
}
|
}
|
||||||
const vibrant = getVibrant(image, true);
|
const vibrant = getVibrant(image, true);
|
||||||
const BLEND = "hsl";
|
const BLEND = 'hsl'
|
||||||
const darkAccent = chroma
|
const darkAccent = chroma
|
||||||
.mix(vibrant.Vibrant, "hsla(216, 0%, 90%, 1)", 0.6, BLEND)
|
.mix(vibrant.Vibrant, "hsla(216, 0%, 90%, 1)", 0.6, BLEND)
|
||||||
.hex();
|
.hex();
|
||||||
@ -154,7 +145,7 @@ const GalleryImage = ({ data, location: { state } }) => {
|
|||||||
ar > 1
|
ar > 1
|
||||||
? "flex-col"
|
? "flex-col"
|
||||||
: "portrait:mx-auto landscape:mx-5 landscape:flex-row-reverse portrait:flex-col";
|
: "portrait:mx-auto landscape:mx-5 landscape:flex-row-reverse portrait:flex-col";
|
||||||
const verticalPad = ar > 1 ? "180px" : "20px";
|
const verticalPad = ar > 1 ? "250px" : "100px";
|
||||||
|
|
||||||
const shutterSpeed = React.useMemo(
|
const shutterSpeed = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
@ -1,37 +1,44 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { Link } from "gatsby";
|
import Checkmark from "@spectrum-icons/workflow/Checkmark";
|
||||||
|
|
||||||
interface KeywordsPickerProps {
|
interface KeywordsPickerProps {
|
||||||
keywords: string[];
|
keywords: string[];
|
||||||
value: string | null;
|
value: string | null;
|
||||||
getHref: (value: string | null, selected: boolean) => string;
|
onChange: (val: string | null) => void;
|
||||||
onPick: (value: string | null) => void;
|
|
||||||
}
|
}
|
||||||
const KeywordsPicker = ({ keywords, value, getHref, onPick }: KeywordsPickerProps) => {
|
const KeywordsPicker = ({ keywords, value, onChange }: KeywordsPickerProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="mx-2 mt-2">
|
<div className="mx-2 mt-2">
|
||||||
<span className="text-xs text-black">Collections</span>
|
<span className="text-xs text-black">
|
||||||
|
Collections
|
||||||
|
</span>
|
||||||
<ul className="flex gap-1 flex-wrap mt-1 mb-2">
|
<ul className="flex gap-1 flex-wrap mt-1 mb-2">
|
||||||
{keywords.map((keyword) => {
|
{keywords.map((keyword) => {
|
||||||
const selected = value === keyword;
|
const selected = value === keyword;
|
||||||
return (
|
return (
|
||||||
<li key={keyword}>
|
<li key={keyword}>
|
||||||
<Link
|
<button
|
||||||
className={classNames(
|
className={classNames(
|
||||||
`py-[5px] px-3 rounded-full text-sm block`,
|
`py-[5px] px-3 rounded-full text-sm`,
|
||||||
`text-black border border-gray-400`,
|
`text-black border border-black`,
|
||||||
selected
|
selected
|
||||||
? "bg-black/10 font-bold"
|
? "bg-transparentblack font-bold"
|
||||||
: `bg-white
|
: `bg-white
|
||||||
hover:bg-black/10`
|
hover:bg-transparentblack`
|
||||||
)}
|
)}
|
||||||
onClick={() => onPick(keyword)}
|
onClick={() => (selected ? onChange(null) : onChange(keyword))}
|
||||||
replace={false}
|
type="button"
|
||||||
to={getHref(keyword, selected)}
|
|
||||||
>
|
>
|
||||||
{keyword}{" "}
|
{keyword}{" "}
|
||||||
</Link>
|
{/* {selected && (
|
||||||
|
<Checkmark
|
||||||
|
UNSAFE_className="mx-1"
|
||||||
|
UNSAFE_style={{ width: "15px" }}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)} */}
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -91,8 +91,8 @@ function Option({ item, state }: OptionProps) {
|
|||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
{...optionProps}
|
{...optionProps}
|
||||||
className={`p-2 outline-none cursor-default flex items-center justify-between ${text} text-sm ${
|
className={`p-3 outline-none cursor-default flex items-center justify-between ${text} text-sm ${
|
||||||
isFocused ? "bg-black/10" : ""
|
isFocused ? "bg-transparentblack" : ""
|
||||||
} ${isSelected ? "font-bold" : ""}`}
|
} ${isSelected ? "font-bold" : ""}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
|
@ -18,25 +18,23 @@ interface Row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface MasonryGalleryProps {
|
interface MasonryGalleryProps {
|
||||||
images: readonly GalleryImage[];
|
images: GalleryImage[];
|
||||||
aspectsByBreakpoint: {
|
aspectsByBreakpoint: {
|
||||||
[breakpoint: string]: number;
|
[breakpoint: string]: number;
|
||||||
};
|
};
|
||||||
debugHue?: boolean;
|
debugHue?: boolean;
|
||||||
dataFn?: (image: GalleryImage) => string[] | null;
|
debugRating?: boolean;
|
||||||
linkState?: object;
|
linkState?: object;
|
||||||
showPalette?: boolean;
|
showPalette?: boolean;
|
||||||
singleRow?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MasonryGallery = ({
|
const MasonryGallery = ({
|
||||||
images: _images,
|
images,
|
||||||
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
aspectsByBreakpoint: aspectTargetsByBreakpoint,
|
||||||
debugHue,
|
debugHue,
|
||||||
dataFn,
|
debugRating,
|
||||||
linkState,
|
linkState,
|
||||||
showPalette,
|
showPalette,
|
||||||
singleRow,
|
|
||||||
}: MasonryGalleryProps) => {
|
}: MasonryGalleryProps) => {
|
||||||
const [isClient, setIsClient] = React.useState(false);
|
const [isClient, setIsClient] = React.useState(false);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -47,57 +45,65 @@ const MasonryGallery = ({
|
|||||||
[aspectTargetsByBreakpoint]
|
[aspectTargetsByBreakpoint]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// const { observe, currentBreakpoint } = useDimensions({
|
||||||
|
// breakpoints,
|
||||||
|
// });
|
||||||
|
|
||||||
const { breakpoint } = useBreakpoint(breakpoints, "xs");
|
const { breakpoint } = useBreakpoint(breakpoints, "xs");
|
||||||
|
|
||||||
|
// const breakpoint = currentBreakpoint.length ? currentBreakpoint : "xs";
|
||||||
const galleryWidth = `calc(100vw - ${
|
const galleryWidth = `calc(100vw - ${
|
||||||
breakpoint === "xs" || breakpoint === "sm" ? "32" : "160"
|
breakpoint === "xs" || breakpoint === "sm" ? "32" : "160"
|
||||||
}px)`;
|
}px)`;
|
||||||
|
|
||||||
const aspectRatios = React.useMemo(
|
const aspectRatios = React.useMemo(
|
||||||
() => R.map(getAspectRatio, _images).filter(Boolean),
|
() => R.map(getAspectRatio, images).filter(Boolean),
|
||||||
[_images]
|
[images]
|
||||||
) as number[];
|
) as number[];
|
||||||
|
|
||||||
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
const targetAspect = aspectTargetsByBreakpoint[breakpoint];
|
||||||
const rows = React.useMemo(() => {
|
const rows = React.useMemo(
|
||||||
const _rows: Row[] = [{ aspect: 0, startIndex: 0, images: 0 }];
|
() =>
|
||||||
|
R.pipe(
|
||||||
for (const currentAspect of aspectRatios) {
|
R.reduce(
|
||||||
const currentRow = _rows[_rows.length - 1];
|
(acc, currentAspect: number): Row[] => {
|
||||||
const currentDiff = Math.abs(targetAspect - currentRow.aspect);
|
const currentRow = acc.pop()!;
|
||||||
const diffIfImageIsAddedToCurrentRow = Math.abs(
|
const currentDiff = Math.abs(targetAspect - currentRow.aspect);
|
||||||
targetAspect - (currentRow.aspect + currentAspect)
|
const diffIfImageIsAddedToCurrentRow = Math.abs(
|
||||||
);
|
targetAspect - (currentRow.aspect + currentAspect)
|
||||||
|
);
|
||||||
// does adding current image to our row get us closer to our target aspect ratio?
|
// add image to current row if it gets us closer to our target aspect ratio
|
||||||
if (currentDiff > diffIfImageIsAddedToCurrentRow) {
|
if (currentDiff > diffIfImageIsAddedToCurrentRow) {
|
||||||
currentRow.aspect += currentAspect;
|
return [
|
||||||
currentRow.images += 1;
|
...acc,
|
||||||
// _rows.push(currentRow);
|
{
|
||||||
continue;
|
aspect: currentRow.aspect + currentAspect,
|
||||||
}
|
images: currentRow.images + 1,
|
||||||
|
startIndex: currentRow.startIndex,
|
||||||
if (singleRow) {
|
},
|
||||||
break;
|
];
|
||||||
}
|
}
|
||||||
|
return [
|
||||||
// start a new row
|
...acc,
|
||||||
_rows.push({
|
currentRow,
|
||||||
aspect: currentAspect,
|
{
|
||||||
images: 1,
|
aspect: currentAspect,
|
||||||
startIndex: currentRow.startIndex + currentRow.images,
|
images: 1,
|
||||||
});
|
startIndex: currentRow.startIndex + currentRow.images,
|
||||||
}
|
} as Row,
|
||||||
|
];
|
||||||
return R.indexBy(R.prop("startIndex"), _rows);
|
},
|
||||||
}, [aspectRatios, targetAspect, singleRow]);
|
[{ aspect: 0, startIndex: 0, images: 0 }] as Row[]
|
||||||
|
),
|
||||||
const sortedImageList = React.useMemo(
|
R.indexBy(R.prop("startIndex"))
|
||||||
() => _images.map((image) => image.base),
|
)(aspectRatios),
|
||||||
[_images]
|
[aspectRatios, targetAspect]
|
||||||
);
|
);
|
||||||
|
|
||||||
const images = singleRow ? _images.slice(0, rows[0].images) : _images;
|
const sortedImageList = React.useMemo(
|
||||||
|
() => images.map((image) => image.base),
|
||||||
|
[images]
|
||||||
|
);
|
||||||
|
|
||||||
let cursor = 0;
|
let cursor = 0;
|
||||||
return (
|
return (
|
||||||
@ -119,11 +125,9 @@ const MasonryGallery = ({
|
|||||||
}
|
}
|
||||||
const rowAspectRatioSum = currentRow.aspect;
|
const rowAspectRatioSum = currentRow.aspect;
|
||||||
const ar = getAspectRatio(image);
|
const ar = getAspectRatio(image);
|
||||||
let width: string;
|
let width;
|
||||||
let height = `calc(${galleryWidth} / ${rowAspectRatioSum} ${
|
let height = `calc(${galleryWidth} / ${rowAspectRatioSum} ${showPalette ? "+ 10px" : "- 10px"})`;
|
||||||
showPalette ? "+ 10px" : "- 10px"
|
if (rowAspectRatioSum < targetAspect * 0.66) {
|
||||||
})`;
|
|
||||||
if (rowAspectRatioSum < targetAspect * 0.66 && !singleRow) {
|
|
||||||
// incomplete row, render stuff at "ideal" sizes instead of filling width
|
// incomplete row, render stuff at "ideal" sizes instead of filling width
|
||||||
width = `calc(calc(100vw - 160px) / ${targetAspect / ar})`;
|
width = `calc(calc(100vw - 160px) / ${targetAspect / ar})`;
|
||||||
height = "unset";
|
height = "unset";
|
||||||
@ -134,12 +138,10 @@ const MasonryGallery = ({
|
|||||||
const vibrant = getVibrant(image);
|
const vibrant = getVibrant(image);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const img = getImage(image);
|
const img = getImage(image);
|
||||||
|
|
||||||
const data = dataFn ? dataFn(image) : null;
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
className="border-8 border-white overflow-hidden relative"
|
className={classNames("border-8 border-white overflow-hidden")}
|
||||||
id={singleRow ? undefined : image.base}
|
id={image.base}
|
||||||
key={`${image.base}`}
|
key={`${image.base}`}
|
||||||
state={{
|
state={{
|
||||||
...linkState,
|
...linkState,
|
||||||
@ -159,68 +161,47 @@ const MasonryGallery = ({
|
|||||||
}}
|
}}
|
||||||
to={`/photogallery/${image.base}/`}
|
to={`/photogallery/${image.base}/`}
|
||||||
>
|
>
|
||||||
{data && (
|
{debugRating && (
|
||||||
<div className="text-white z-20 absolute flex flex-col items-start">
|
<span className="text-white z-20 absolute bg-black">
|
||||||
{data.map((dataString, i) => (
|
rating: {image.fields?.imageMeta?.meta?.Rating}
|
||||||
<span
|
</span>
|
||||||
className="bg-black/30 backdrop-blur shadow p-[2px] m-[2px] max-w-full"
|
|
||||||
key={i}
|
|
||||||
>
|
|
||||||
{dataString}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{img && (
|
{img && (
|
||||||
<div
|
<div className={`h-full ${showPalette && "grid grid-rows-[1fr_20px]"}`}>
|
||||||
className={`h-full ${
|
|
||||||
showPalette && "grid grid-rows-[1fr_20px]"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<GatsbyImage
|
<GatsbyImage
|
||||||
alt={
|
alt={getName(image)}
|
||||||
image.fields?.imageMeta?.meta?.Keywords?.length
|
|
||||||
? `image of ${image.fields?.imageMeta?.meta?.Keywords.join(
|
|
||||||
" and "
|
|
||||||
)}. ${getName(image)}`
|
|
||||||
: getName(image)
|
|
||||||
}
|
|
||||||
className="w-full"
|
className="w-full"
|
||||||
image={img}
|
image={img}
|
||||||
objectFit="cover"
|
objectFit="cover"
|
||||||
/>
|
/>
|
||||||
{showPalette && vibrant && (
|
{ showPalette && vibrant && <div className="grid grid-cols-6 flex-shrink-0 h-[20px] w-full">
|
||||||
<div className="grid grid-cols-6 flex-shrink-0 h-[20px] w-full">
|
<div
|
||||||
<div
|
style={{ background: `rgba(${vibrant.Vibrant?.join(",")})` }}
|
||||||
style={{
|
></div>
|
||||||
background: `rgba(${vibrant.Vibrant?.join(",")})`,
|
<div
|
||||||
}}
|
style={{
|
||||||
></div>
|
background: `rgb(${vibrant.LightVibrant?.join(",")})`,
|
||||||
<div
|
}}
|
||||||
style={{
|
></div>
|
||||||
background: `rgb(${vibrant.LightVibrant?.join(",")})`,
|
<div
|
||||||
}}
|
style={{
|
||||||
></div>
|
background: `rgb(${vibrant.DarkVibrant?.join(",")})`,
|
||||||
<div
|
}}
|
||||||
style={{
|
></div>
|
||||||
background: `rgb(${vibrant.DarkVibrant?.join(",")})`,
|
<div
|
||||||
}}
|
style={{ background: `rgb(${vibrant.Muted?.join(",")})` }}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
style={{ background: `rgb(${vibrant.Muted?.join(",")})` }}
|
style={{
|
||||||
></div>
|
background: `rgb(${vibrant.LightMuted?.join(",")})`,
|
||||||
<div
|
}}
|
||||||
style={{
|
></div>
|
||||||
background: `rgb(${vibrant.LightMuted?.join(",")})`,
|
<div
|
||||||
}}
|
style={{
|
||||||
></div>
|
background: `rgb(${vibrant.DarkMuted?.join(",")})`,
|
||||||
<div
|
}}
|
||||||
style={{
|
></div>
|
||||||
background: `rgb(${vibrant.DarkMuted?.join(",")})`,
|
</div>}
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
import React, { useRef, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import { Link, navigate } from "gatsby";
|
import { Link } from "gatsby";
|
||||||
import { Popover } from "react-tiny-popover";
|
import { Popover } from "react-tiny-popover";
|
||||||
import { StaticImage } from "gatsby-plugin-image";
|
|
||||||
|
|
||||||
const navClasses =
|
const navClasses =
|
||||||
"hover:underline hover:bg-black/10 block p-3 text-black flex-shrink-0 whitespace-nowrap";
|
"hover:underline hover:bg-transparentblack block p-3 text-black";
|
||||||
|
|
||||||
const ExternalLinks = () => (
|
const ExternalLinks = () => (
|
||||||
<ul
|
<ul
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"z-30 overflow-hidden bg-vibrant-dark",
|
"z-30 overflow-hidden bg-vibrant-dark",
|
||||||
"rounded shadow-lg border border-gray-400"
|
"rounded shadow border border-vibrant-light"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
@ -88,56 +87,17 @@ interface NavProps {
|
|||||||
|
|
||||||
const Nav = ({ internalLinks, className }: NavProps) => {
|
const Nav = ({ internalLinks, className }: NavProps) => {
|
||||||
const [linksMenu, setLinksMenu] = useState(false);
|
const [linksMenu, setLinksMenu] = useState(false);
|
||||||
const faceClicks = useRef(0);
|
|
||||||
const faceLastClicked = useRef(0);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"my-4 flex flex-col-reverse md:flex-row",
|
"my-4 flex flex-col-reverse md:flex-row items-center w-full font-sans px-4 md:px-8",
|
||||||
"justify-between",
|
|
||||||
"items-center w-full font-sans px-4 md:px-8",
|
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex flex-auto items-center">
|
<div className="md:flex items-baseline flex-auto">
|
||||||
<div
|
<h1 className="font-bold mr-2">Chuck Dries</h1>
|
||||||
className={classnames(
|
<h2 className="text-md">Software Engineer & Photographer</h2>
|
||||||
"h-[120px] w-[120px] mr-4 my-5 flex-shrink-0"
|
|
||||||
)}
|
|
||||||
onClick={() => {
|
|
||||||
const prevClick = faceLastClicked.current;
|
|
||||||
faceLastClicked.current = Date.now();
|
|
||||||
if (prevClick > 0 && faceLastClicked.current - prevClick > 500) {
|
|
||||||
console.log('too slow!')
|
|
||||||
faceClicks.current = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (faceClicks.current === 4) {
|
|
||||||
navigate("/photogallery/?debug=true");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
faceClicks.current += 1;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<StaticImage
|
|
||||||
alt="A picture of me"
|
|
||||||
className="relative"
|
|
||||||
placeholder="tracedSVG"
|
|
||||||
src="../images/circle-profile.png"
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
// top: "-70%",
|
|
||||||
// left: "-50%",
|
|
||||||
// width: "200%",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="items-baseline">
|
|
||||||
<h1 className="font-bold mr-2">Chuck Dries</h1>
|
|
||||||
<h2 className="text-md">Software Engineer & Photographer</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
|
@ -48,8 +48,8 @@ export function Select<T extends object>(props: AriaSelectProps<T>) {
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
{...mergeProps(buttonProps, focusProps)}
|
{...mergeProps(buttonProps, focusProps)}
|
||||||
className={`py-[5px] px-3 w-[150px] flex flex-row items-center justify-between overflow-hidden cursor-default rounded border hover:bg-black/10 ${
|
className={`py-[5px] px-3 w-[150px] flex flex-row items-center justify-between overflow-hidden cursor-default rounded border hover:bg-transparentblack ${
|
||||||
isFocusVisible ? "border-green-700" : "border-gray-400"
|
isFocusVisible ? "border-green-500" : "border-black"
|
||||||
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
} ${state.isOpen ? "bg-gray-100" : "bg-white"}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
import {useToggleState} from 'react-stately';
|
|
||||||
import {AriaToggleButtonProps, useToggleButton} from 'react-aria';
|
|
||||||
import {useRef} from 'react';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export function ToggleButton(props: AriaToggleButtonProps) {
|
|
||||||
let ref = useRef(null);
|
|
||||||
let state = useToggleState(props);
|
|
||||||
let { buttonProps, isPressed } = useToggleButton(props, state, ref);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
{...buttonProps}
|
|
||||||
className={classNames(buttonProps.className, "py-[3px] px-2 mx-1 rounded")}
|
|
||||||
ref={ref}
|
|
||||||
style={{
|
|
||||||
background: isPressed
|
|
||||||
? state.isSelected ? 'darkgreen' : 'gray'
|
|
||||||
: state.isSelected
|
|
||||||
? 'green'
|
|
||||||
: 'lightgray',
|
|
||||||
color: state.isSelected ? 'white' : 'black',
|
|
||||||
userSelect: 'none',
|
|
||||||
WebkitUserSelect: 'none',
|
|
||||||
border: 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{props.children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
}
|
|
384
src/gatsby-types.d.ts
vendored
384
src/gatsby-types.d.ts
vendored
@ -571,7 +571,6 @@ type FileFieldsFilterInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMeta = {
|
type FileFieldsImageMeta = {
|
||||||
readonly datePublished: Maybe<Scalars['Date']>;
|
|
||||||
readonly dateTaken: Maybe<Scalars['Date']>;
|
readonly dateTaken: Maybe<Scalars['Date']>;
|
||||||
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
readonly dominantHue: Maybe<ReadonlyArray<Maybe<Scalars['Float']>>>;
|
||||||
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
readonly meta: Maybe<FileFieldsImageMetaMeta>;
|
||||||
@ -580,14 +579,6 @@ type FileFieldsImageMeta = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
type FileFieldsImageMeta_datePublishedArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type FileFieldsImageMeta_dateTakenArgs = {
|
type FileFieldsImageMeta_dateTakenArgs = {
|
||||||
difference: InputMaybe<Scalars['String']>;
|
difference: InputMaybe<Scalars['String']>;
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
formatString: InputMaybe<Scalars['String']>;
|
||||||
@ -596,7 +587,6 @@ type FileFieldsImageMeta_dateTakenArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFieldSelector = {
|
type FileFieldsImageMetaFieldSelector = {
|
||||||
readonly datePublished: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
readonly dateTaken: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
readonly dominantHue: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFieldSelector>;
|
||||||
@ -605,7 +595,6 @@ type FileFieldsImageMetaFieldSelector = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaFilterInput = {
|
type FileFieldsImageMetaFilterInput = {
|
||||||
readonly datePublished: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
readonly dateTaken: InputMaybe<DateQueryOperatorInput>;
|
||||||
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
readonly dominantHue: InputMaybe<FloatQueryOperatorInput>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaFilterInput>;
|
||||||
@ -628,7 +617,6 @@ type FileFieldsImageMetaMeta = {
|
|||||||
readonly Location: Maybe<Scalars['String']>;
|
readonly Location: Maybe<Scalars['String']>;
|
||||||
readonly Make: Maybe<Scalars['String']>;
|
readonly Make: Maybe<Scalars['String']>;
|
||||||
readonly Model: Maybe<Scalars['String']>;
|
readonly Model: Maybe<Scalars['String']>;
|
||||||
readonly ModifyDate: Maybe<Scalars['Date']>;
|
|
||||||
readonly ObjectName: Maybe<Scalars['String']>;
|
readonly ObjectName: Maybe<Scalars['String']>;
|
||||||
readonly Rating: Maybe<Scalars['Int']>;
|
readonly Rating: Maybe<Scalars['Int']>;
|
||||||
readonly ShutterSpeedValue: Maybe<Scalars['Float']>;
|
readonly ShutterSpeedValue: Maybe<Scalars['Float']>;
|
||||||
@ -651,14 +639,6 @@ type FileFieldsImageMetaMeta_DateTimeOriginalArgs = {
|
|||||||
locale: InputMaybe<Scalars['String']>;
|
locale: InputMaybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
type FileFieldsImageMetaMeta_ModifyDateArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type FileFieldsImageMetaMetaFieldSelector = {
|
type FileFieldsImageMetaMetaFieldSelector = {
|
||||||
readonly ApertureValue: InputMaybe<FieldSelectorEnum>;
|
readonly ApertureValue: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Caption: InputMaybe<FieldSelectorEnum>;
|
readonly Caption: InputMaybe<FieldSelectorEnum>;
|
||||||
@ -674,7 +654,6 @@ type FileFieldsImageMetaMetaFieldSelector = {
|
|||||||
readonly Location: InputMaybe<FieldSelectorEnum>;
|
readonly Location: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Make: InputMaybe<FieldSelectorEnum>;
|
readonly Make: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Model: InputMaybe<FieldSelectorEnum>;
|
readonly Model: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly ModifyDate: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly ObjectName: InputMaybe<FieldSelectorEnum>;
|
readonly ObjectName: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly Rating: InputMaybe<FieldSelectorEnum>;
|
readonly Rating: InputMaybe<FieldSelectorEnum>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<FieldSelectorEnum>;
|
readonly ShutterSpeedValue: InputMaybe<FieldSelectorEnum>;
|
||||||
@ -696,7 +675,6 @@ type FileFieldsImageMetaMetaFilterInput = {
|
|||||||
readonly Location: InputMaybe<StringQueryOperatorInput>;
|
readonly Location: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Make: InputMaybe<StringQueryOperatorInput>;
|
readonly Make: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Model: InputMaybe<StringQueryOperatorInput>;
|
readonly Model: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly ModifyDate: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly ObjectName: InputMaybe<StringQueryOperatorInput>;
|
readonly ObjectName: InputMaybe<StringQueryOperatorInput>;
|
||||||
readonly Rating: InputMaybe<IntQueryOperatorInput>;
|
readonly Rating: InputMaybe<IntQueryOperatorInput>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<FloatQueryOperatorInput>;
|
readonly ShutterSpeedValue: InputMaybe<FloatQueryOperatorInput>;
|
||||||
@ -718,7 +696,6 @@ type FileFieldsImageMetaMetaSortInput = {
|
|||||||
readonly Location: InputMaybe<SortOrderEnum>;
|
readonly Location: InputMaybe<SortOrderEnum>;
|
||||||
readonly Make: InputMaybe<SortOrderEnum>;
|
readonly Make: InputMaybe<SortOrderEnum>;
|
||||||
readonly Model: InputMaybe<SortOrderEnum>;
|
readonly Model: InputMaybe<SortOrderEnum>;
|
||||||
readonly ModifyDate: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly ObjectName: InputMaybe<SortOrderEnum>;
|
readonly ObjectName: InputMaybe<SortOrderEnum>;
|
||||||
readonly Rating: InputMaybe<SortOrderEnum>;
|
readonly Rating: InputMaybe<SortOrderEnum>;
|
||||||
readonly ShutterSpeedValue: InputMaybe<SortOrderEnum>;
|
readonly ShutterSpeedValue: InputMaybe<SortOrderEnum>;
|
||||||
@ -726,7 +703,6 @@ type FileFieldsImageMetaMetaSortInput = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type FileFieldsImageMetaSortInput = {
|
type FileFieldsImageMetaSortInput = {
|
||||||
readonly datePublished: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
readonly dateTaken: InputMaybe<SortOrderEnum>;
|
||||||
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
readonly dominantHue: InputMaybe<SortOrderEnum>;
|
||||||
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
readonly meta: InputMaybe<FileFieldsImageMetaMetaSortInput>;
|
||||||
@ -1532,7 +1508,6 @@ type Query = {
|
|||||||
readonly allSiteFunction: SiteFunctionConnection;
|
readonly allSiteFunction: SiteFunctionConnection;
|
||||||
readonly allSitePage: SitePageConnection;
|
readonly allSitePage: SitePageConnection;
|
||||||
readonly allSitePlugin: SitePluginConnection;
|
readonly allSitePlugin: SitePluginConnection;
|
||||||
readonly allStaticImage: StaticImageConnection;
|
|
||||||
readonly directory: Maybe<Directory>;
|
readonly directory: Maybe<Directory>;
|
||||||
readonly file: Maybe<File>;
|
readonly file: Maybe<File>;
|
||||||
readonly imageSharp: Maybe<ImageSharp>;
|
readonly imageSharp: Maybe<ImageSharp>;
|
||||||
@ -1541,7 +1516,6 @@ type Query = {
|
|||||||
readonly siteFunction: Maybe<SiteFunction>;
|
readonly siteFunction: Maybe<SiteFunction>;
|
||||||
readonly sitePage: Maybe<SitePage>;
|
readonly sitePage: Maybe<SitePage>;
|
||||||
readonly sitePlugin: Maybe<SitePlugin>;
|
readonly sitePlugin: Maybe<SitePlugin>;
|
||||||
readonly staticImage: Maybe<StaticImage>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1609,14 +1583,6 @@ type Query_allSitePluginArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
type Query_allStaticImageArgs = {
|
|
||||||
filter: InputMaybe<StaticImageFilterInput>;
|
|
||||||
limit: InputMaybe<Scalars['Int']>;
|
|
||||||
skip: InputMaybe<Scalars['Int']>;
|
|
||||||
sort: InputMaybe<ReadonlyArray<InputMaybe<StaticImageSortInput>>>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type Query_directoryArgs = {
|
type Query_directoryArgs = {
|
||||||
absolutePath: InputMaybe<StringQueryOperatorInput>;
|
absolutePath: InputMaybe<StringQueryOperatorInput>;
|
||||||
accessTime: InputMaybe<DateQueryOperatorInput>;
|
accessTime: InputMaybe<DateQueryOperatorInput>;
|
||||||
@ -1786,46 +1752,6 @@ type Query_sitePluginArgs = {
|
|||||||
version: InputMaybe<StringQueryOperatorInput>;
|
version: InputMaybe<StringQueryOperatorInput>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
type Query_staticImageArgs = {
|
|
||||||
absolutePath: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
accessTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
atime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
atimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
base: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
birthTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
birthtime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
birthtimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
blksize: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
blocks: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
changeTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
children: InputMaybe<NodeFilterListInput>;
|
|
||||||
ctime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
ctimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
dev: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
dir: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
ext: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
extension: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
id: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
ino: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
internal: InputMaybe<InternalFilterInput>;
|
|
||||||
mode: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
modifiedTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
mtime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
mtimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
name: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
nlink: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
parent: InputMaybe<NodeFilterInput>;
|
|
||||||
prettySize: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
rdev: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
relativeDirectory: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
relativePath: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
root: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
size: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
sourceInstanceName: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
uid: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Site = Node & {
|
type Site = Node & {
|
||||||
readonly buildTime: Maybe<Scalars['Date']>;
|
readonly buildTime: Maybe<Scalars['Date']>;
|
||||||
readonly children: ReadonlyArray<Node>;
|
readonly children: ReadonlyArray<Node>;
|
||||||
@ -2592,312 +2518,6 @@ type SortOrderEnum =
|
|||||||
| 'ASC'
|
| 'ASC'
|
||||||
| 'DESC';
|
| 'DESC';
|
||||||
|
|
||||||
type StaticImage = Node & {
|
|
||||||
readonly absolutePath: Maybe<Scalars['String']>;
|
|
||||||
readonly accessTime: Maybe<Scalars['Date']>;
|
|
||||||
readonly atime: Maybe<Scalars['Date']>;
|
|
||||||
readonly atimeMs: Maybe<Scalars['Float']>;
|
|
||||||
readonly base: Maybe<Scalars['String']>;
|
|
||||||
readonly birthTime: Maybe<Scalars['Date']>;
|
|
||||||
readonly birthtime: Maybe<Scalars['Date']>;
|
|
||||||
readonly birthtimeMs: Maybe<Scalars['Float']>;
|
|
||||||
readonly blksize: Maybe<Scalars['Int']>;
|
|
||||||
readonly blocks: Maybe<Scalars['Int']>;
|
|
||||||
readonly changeTime: Maybe<Scalars['Date']>;
|
|
||||||
readonly children: ReadonlyArray<Node>;
|
|
||||||
readonly ctime: Maybe<Scalars['Date']>;
|
|
||||||
readonly ctimeMs: Maybe<Scalars['Float']>;
|
|
||||||
readonly dev: Maybe<Scalars['Int']>;
|
|
||||||
readonly dir: Maybe<Scalars['String']>;
|
|
||||||
readonly ext: Maybe<Scalars['String']>;
|
|
||||||
readonly extension: Maybe<Scalars['String']>;
|
|
||||||
readonly id: Scalars['ID'];
|
|
||||||
readonly ino: Maybe<Scalars['Int']>;
|
|
||||||
readonly internal: Internal;
|
|
||||||
readonly mode: Maybe<Scalars['Int']>;
|
|
||||||
readonly modifiedTime: Maybe<Scalars['Date']>;
|
|
||||||
readonly mtime: Maybe<Scalars['Date']>;
|
|
||||||
readonly mtimeMs: Maybe<Scalars['Float']>;
|
|
||||||
readonly name: Maybe<Scalars['String']>;
|
|
||||||
readonly nlink: Maybe<Scalars['Int']>;
|
|
||||||
readonly parent: Maybe<Node>;
|
|
||||||
readonly prettySize: Maybe<Scalars['String']>;
|
|
||||||
readonly rdev: Maybe<Scalars['Int']>;
|
|
||||||
readonly relativeDirectory: Maybe<Scalars['String']>;
|
|
||||||
readonly relativePath: Maybe<Scalars['String']>;
|
|
||||||
readonly root: Maybe<Scalars['String']>;
|
|
||||||
readonly size: Maybe<Scalars['Int']>;
|
|
||||||
readonly sourceInstanceName: Maybe<Scalars['String']>;
|
|
||||||
readonly uid: Maybe<Scalars['Int']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_accessTimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_atimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_birthTimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_birthtimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_changeTimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_ctimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_modifiedTimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImage_mtimeArgs = {
|
|
||||||
difference: InputMaybe<Scalars['String']>;
|
|
||||||
formatString: InputMaybe<Scalars['String']>;
|
|
||||||
fromNow: InputMaybe<Scalars['Boolean']>;
|
|
||||||
locale: InputMaybe<Scalars['String']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageConnection = {
|
|
||||||
readonly distinct: ReadonlyArray<Scalars['String']>;
|
|
||||||
readonly edges: ReadonlyArray<StaticImageEdge>;
|
|
||||||
readonly group: ReadonlyArray<StaticImageGroupConnection>;
|
|
||||||
readonly max: Maybe<Scalars['Float']>;
|
|
||||||
readonly min: Maybe<Scalars['Float']>;
|
|
||||||
readonly nodes: ReadonlyArray<StaticImage>;
|
|
||||||
readonly pageInfo: PageInfo;
|
|
||||||
readonly sum: Maybe<Scalars['Float']>;
|
|
||||||
readonly totalCount: Scalars['Int'];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageConnection_distinctArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageConnection_groupArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
limit: InputMaybe<Scalars['Int']>;
|
|
||||||
skip: InputMaybe<Scalars['Int']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageConnection_maxArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageConnection_minArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageConnection_sumArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageEdge = {
|
|
||||||
readonly next: Maybe<StaticImage>;
|
|
||||||
readonly node: StaticImage;
|
|
||||||
readonly previous: Maybe<StaticImage>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageFieldSelector = {
|
|
||||||
readonly absolutePath: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly accessTime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly atime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly atimeMs: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly base: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly birthTime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly birthtime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly birthtimeMs: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly blksize: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly blocks: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly changeTime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly children: InputMaybe<NodeFieldSelector>;
|
|
||||||
readonly ctime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly ctimeMs: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly dev: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly dir: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly ext: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly extension: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly id: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly ino: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly internal: InputMaybe<InternalFieldSelector>;
|
|
||||||
readonly mode: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly modifiedTime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly mtime: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly mtimeMs: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly name: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly nlink: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly parent: InputMaybe<NodeFieldSelector>;
|
|
||||||
readonly prettySize: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly rdev: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly relativeDirectory: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly relativePath: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly root: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly size: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly sourceInstanceName: InputMaybe<FieldSelectorEnum>;
|
|
||||||
readonly uid: InputMaybe<FieldSelectorEnum>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageFilterInput = {
|
|
||||||
readonly absolutePath: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly accessTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly atime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly atimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
readonly base: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly birthTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly birthtime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly birthtimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
readonly blksize: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly blocks: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly changeTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly children: InputMaybe<NodeFilterListInput>;
|
|
||||||
readonly ctime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly ctimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
readonly dev: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly dir: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly ext: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly extension: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly id: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly ino: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly internal: InputMaybe<InternalFilterInput>;
|
|
||||||
readonly mode: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly modifiedTime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly mtime: InputMaybe<DateQueryOperatorInput>;
|
|
||||||
readonly mtimeMs: InputMaybe<FloatQueryOperatorInput>;
|
|
||||||
readonly name: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly nlink: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly parent: InputMaybe<NodeFilterInput>;
|
|
||||||
readonly prettySize: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly rdev: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly relativeDirectory: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly relativePath: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly root: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly size: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
readonly sourceInstanceName: InputMaybe<StringQueryOperatorInput>;
|
|
||||||
readonly uid: InputMaybe<IntQueryOperatorInput>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageGroupConnection = {
|
|
||||||
readonly distinct: ReadonlyArray<Scalars['String']>;
|
|
||||||
readonly edges: ReadonlyArray<StaticImageEdge>;
|
|
||||||
readonly field: Scalars['String'];
|
|
||||||
readonly fieldValue: Maybe<Scalars['String']>;
|
|
||||||
readonly group: ReadonlyArray<StaticImageGroupConnection>;
|
|
||||||
readonly max: Maybe<Scalars['Float']>;
|
|
||||||
readonly min: Maybe<Scalars['Float']>;
|
|
||||||
readonly nodes: ReadonlyArray<StaticImage>;
|
|
||||||
readonly pageInfo: PageInfo;
|
|
||||||
readonly sum: Maybe<Scalars['Float']>;
|
|
||||||
readonly totalCount: Scalars['Int'];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageGroupConnection_distinctArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageGroupConnection_groupArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
limit: InputMaybe<Scalars['Int']>;
|
|
||||||
skip: InputMaybe<Scalars['Int']>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageGroupConnection_maxArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageGroupConnection_minArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
type StaticImageGroupConnection_sumArgs = {
|
|
||||||
field: StaticImageFieldSelector;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StaticImageSortInput = {
|
|
||||||
readonly absolutePath: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly accessTime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly atime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly atimeMs: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly base: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly birthTime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly birthtime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly birthtimeMs: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly blksize: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly blocks: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly changeTime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly children: InputMaybe<NodeSortInput>;
|
|
||||||
readonly ctime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly ctimeMs: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly dev: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly dir: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly ext: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly extension: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly id: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly ino: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly internal: InputMaybe<InternalSortInput>;
|
|
||||||
readonly mode: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly modifiedTime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly mtime: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly mtimeMs: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly name: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly nlink: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly parent: InputMaybe<NodeSortInput>;
|
|
||||||
readonly prettySize: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly rdev: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly relativeDirectory: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly relativePath: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly root: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly size: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly sourceInstanceName: InputMaybe<SortOrderEnum>;
|
|
||||||
readonly uid: InputMaybe<SortOrderEnum>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type StringQueryOperatorInput = {
|
type StringQueryOperatorInput = {
|
||||||
readonly eq: InputMaybe<Scalars['String']>;
|
readonly eq: InputMaybe<Scalars['String']>;
|
||||||
readonly glob: InputMaybe<Scalars['String']>;
|
readonly glob: InputMaybe<Scalars['String']>;
|
||||||
@ -2927,12 +2547,10 @@ type GalleryImageQueryVariables = Exact<{
|
|||||||
|
|
||||||
type GalleryImageQuery = { readonly file: { readonly base: string, readonly publicURL: string | null, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly dateTaken: string | null, readonly meta: { readonly Make: string | null, readonly Model: string | null, readonly ExposureTime: number | null, readonly FNumber: number | null, readonly ISO: number | null, readonly DateTimeOriginal: string | null, readonly CreateDate: string | null, readonly ShutterSpeedValue: number | null, readonly ApertureValue: number | null, readonly FocalLength: number | null, readonly LensModel: string | null, readonly ObjectName: string | null, readonly Caption: string | null, readonly Location: string | null, readonly City: string | null, readonly State: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null } | null };
|
type GalleryImageQuery = { readonly file: { readonly base: string, readonly publicURL: string | null, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly dateTaken: string | null, readonly meta: { readonly Make: string | null, readonly Model: string | null, readonly ExposureTime: number | null, readonly FNumber: number | null, readonly ISO: number | null, readonly DateTimeOriginal: string | null, readonly CreateDate: string | null, readonly ShutterSpeedValue: number | null, readonly ApertureValue: number | null, readonly FocalLength: number | null, readonly LensModel: string | null, readonly ObjectName: string | null, readonly Caption: string | null, readonly Location: string | null, readonly City: string | null, readonly State: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null } | null };
|
||||||
|
|
||||||
type GalleryImageFileFragment = { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> };
|
|
||||||
|
|
||||||
type GalleryPageQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
type GalleryPageQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
type GalleryPageQueryQuery = { readonly recents: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> }, readonly all: { readonly nodes: ReadonlyArray<{ readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly datePublished: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null, readonly CreateDate: string | null, readonly ModifyDate: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
type GalleryPageQueryQuery = { readonly allFile: { readonly nodes: ReadonlyArray<{ readonly relativePath: string, readonly base: string, readonly childImageSharp: { readonly gatsbyImageData: import('gatsby-plugin-image').IGatsbyImageData, readonly fluid: { readonly aspectRatio: number } | null } | null, readonly fields: { readonly imageMeta: { readonly vibrantHue: number | null, readonly dominantHue: ReadonlyArray<number | null> | null, readonly dateTaken: string | null, readonly meta: { readonly Keywords: ReadonlyArray<string | null> | null, readonly Rating: number | null, readonly ObjectName: string | null } | null, readonly vibrant: { readonly DarkMuted: ReadonlyArray<number | null> | null, readonly DarkVibrant: ReadonlyArray<number | null> | null, readonly LightMuted: ReadonlyArray<number | null> | null, readonly LightVibrant: ReadonlyArray<number | null> | null, readonly Vibrant: ReadonlyArray<number | null> | null, readonly Muted: ReadonlyArray<number | null> | null } | null } | null } | null }> } };
|
||||||
|
|
||||||
type GatsbyImageSharpFixedFragment = { readonly base64: string | null, readonly width: number, readonly height: number, readonly src: string, readonly srcSet: string };
|
type GatsbyImageSharpFixedFragment = { readonly base64: string | null, readonly width: number, readonly height: number, readonly src: string, readonly srcSet: string };
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 22 MiB |
Binary file not shown.
Before Width: | Height: | Size: 466 KiB |
Binary file not shown.
@ -102,8 +102,8 @@ const IndexPage = ({
|
|||||||
objectFit={browserIsLandscape ? "cover" : "contain"}
|
objectFit={browserIsLandscape ? "cover" : "contain"}
|
||||||
style={{
|
style={{
|
||||||
height: screenHeight
|
height: screenHeight
|
||||||
? `${screenHeight - 268}px`
|
? `${screenHeight - 160}px`
|
||||||
: "calc(100vh-268px)",
|
: "calc(100vh-160px)",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as R from "ramda";
|
import * as R from "ramda";
|
||||||
import { graphql, Link, navigate, PageProps } from "gatsby";
|
import { graphql, PageProps } from "gatsby";
|
||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
|
// import { Picker, Item } from "@adobe/react-spectrum";
|
||||||
|
|
||||||
import MasonryGallery from "../components/MasonryGallery";
|
import MasonryGallery from "../components/MasonryGallery";
|
||||||
import KeywordsPicker from "../components/KeywordsPicker";
|
import KeywordsPicker from "../components/KeywordsPicker";
|
||||||
import {
|
import {
|
||||||
compareDates,
|
|
||||||
getGalleryPageUrl,
|
getGalleryPageUrl,
|
||||||
getHelmetSafeBodyStyle,
|
getHelmetSafeBodyStyle,
|
||||||
getVibrantStyle,
|
getVibrantStyle,
|
||||||
@ -15,56 +15,50 @@ import Nav from "../components/Nav";
|
|||||||
import { Item, Select } from "../components/Select";
|
import { Item, Select } from "../components/Select";
|
||||||
import { Switch } from "../components/Switch";
|
import { Switch } from "../components/Switch";
|
||||||
import ColorPalette from "@spectrum-icons/workflow/ColorPalette";
|
import ColorPalette from "@spectrum-icons/workflow/ColorPalette";
|
||||||
import { ToggleButton } from "../components/ToggleButton";
|
|
||||||
|
|
||||||
const SORT_KEYS = {
|
const SORT_KEYS = {
|
||||||
hue: ["fields", "imageMeta", "vibrantHue"],
|
hue: ["fields", "imageMeta", "vibrantHue"],
|
||||||
rating: ["fields", "imageMeta", "meta", "Rating"],
|
rating: ["fields", "imageMeta", "meta", "Rating"],
|
||||||
// hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
hue_debug: ["fields", "imageMeta", "dominantHue", 0],
|
||||||
hue_debug: ["fields", "imageMeta", "dominantHue", "0"],
|
date: [],
|
||||||
date: ["fields", "imageMeta", "dateTaken"],
|
|
||||||
datePublished: ["fields", "imageMeta", "datePublished"],
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type GalleryImage =
|
export type GalleryImage =
|
||||||
Queries.GalleryPageQueryQuery["all"]["nodes"][number];
|
Queries.GalleryPageQueryQuery["allFile"]["nodes"][number];
|
||||||
|
|
||||||
function smartCompareDates(
|
const GalleryPage = ({ data }: PageProps<Queries.GalleryPageQueryQuery>) => {
|
||||||
key: keyof typeof SORT_KEYS,
|
const hash =
|
||||||
left: GalleryImage,
|
typeof window !== "undefined" ? window.location.hash.replace("#", "") : "";
|
||||||
right: GalleryImage
|
|
||||||
) {
|
|
||||||
let diff = compareDates(SORT_KEYS[key], left, right);
|
|
||||||
if (diff !== 0) {
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
return compareDates(SORT_KEYS.date, left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
const GalleryPage = ({
|
const [hashCleared, setHashCleared] = React.useState(false); // eslint-disable-line no-unused-vars
|
||||||
data,
|
// ^ used just to force a re-render with the cleared hash value (I know, it's a smell for sure)
|
||||||
location,
|
const [filterKeyword, _setKeyword] = React.useState(null as string | null);
|
||||||
}: PageProps<Queries.GalleryPageQueryQuery>) => {
|
const [sortKey, _setSortKey] = React.useState("rating" as string);
|
||||||
const hash = location.hash ? location.hash.replace("#", "") : "";
|
const showDebug =
|
||||||
|
typeof window !== "undefined" &&
|
||||||
const params = new URLSearchParams(location.search);
|
window.location.search.includes("debug=true");
|
||||||
const filterKeyword = params.get("filter");
|
|
||||||
const sortKey = params.get("sort") ?? "rating";
|
|
||||||
|
|
||||||
const showDebug = Boolean(params.get("debug")?.length);
|
|
||||||
const [showPalette, setShowPalette] = React.useState(false);
|
const [showPalette, setShowPalette] = React.useState(false);
|
||||||
|
|
||||||
const onKeywordPick = React.useCallback((newKeyword: string | null) => {
|
const setKeyword = React.useCallback(
|
||||||
if (newKeyword) {
|
(newKeyword: string | null) => {
|
||||||
try {
|
if (newKeyword) {
|
||||||
window.plausible("Filter Keyword", {
|
try {
|
||||||
props: { keyword: newKeyword },
|
window.plausible("Filter Keyword", {
|
||||||
});
|
props: { keyword: newKeyword },
|
||||||
} catch (e) {
|
});
|
||||||
// do nothing
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
_setKeyword(newKeyword);
|
||||||
}, []);
|
window.history.replaceState(
|
||||||
|
null,
|
||||||
|
"",
|
||||||
|
getGalleryPageUrl({ keyword: newKeyword, sortKey }, hash)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[_setKeyword, sortKey, hash]
|
||||||
|
);
|
||||||
|
|
||||||
const setSortKey = React.useCallback(
|
const setSortKey = React.useCallback(
|
||||||
(newSortKey: string) => {
|
(newSortKey: string) => {
|
||||||
@ -75,65 +69,75 @@ const GalleryPage = ({
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
navigate(
|
_setSortKey(newSortKey);
|
||||||
getGalleryPageUrl(
|
window.history.replaceState(
|
||||||
{ sortKey: newSortKey, keyword: filterKeyword, showDebug },
|
null,
|
||||||
hash
|
"",
|
||||||
)
|
getGalleryPageUrl({ sortKey: newSortKey, keyword: filterKeyword }, hash)
|
||||||
// { replace: true }
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[filterKeyword, hash, showDebug]
|
[_setSortKey, filterKeyword, hash]
|
||||||
);
|
);
|
||||||
|
|
||||||
const removeHash = React.useCallback(() => {
|
const removeHash = React.useCallback(() => {
|
||||||
if (!hash.length) {
|
const url = new URL(
|
||||||
|
typeof window !== "undefined"
|
||||||
|
? window.location.href.toString()
|
||||||
|
: "https://chuckdries.com/photogallery/"
|
||||||
|
);
|
||||||
|
|
||||||
|
url.hash = "";
|
||||||
|
window.history.replaceState(null, "", url.href.toString());
|
||||||
|
window.removeEventListener("wheel", removeHash);
|
||||||
|
setHashCleared(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const scrollIntoView = React.useCallback(() => {
|
||||||
|
if (!hash) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('remove hash')
|
const el = document.getElementById(hash);
|
||||||
navigate(
|
if (!el) {
|
||||||
getGalleryPageUrl({ sortKey, keyword: filterKeyword, showDebug }, ""),
|
return;
|
||||||
{ replace: true }
|
}
|
||||||
);
|
el.scrollIntoView({
|
||||||
window.removeEventListener("scroll", removeHash);
|
block: "center",
|
||||||
}, [hash, sortKey, filterKeyword, showDebug]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
// window.addEventListener("scroll", removeHash);
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("scroll", removeHash);
|
|
||||||
};
|
|
||||||
}, [removeHash]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
// hacky but it works for now
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
// don't scroll into view if user got here with back button or if we just cleared it
|
|
||||||
if (!hash.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const el = document.getElementById(hash);
|
|
||||||
if (!el) {
|
|
||||||
console.log("⚠️failed to find hash");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("scrolling into view manually", el.offsetTop);
|
|
||||||
el.scrollIntoView({
|
|
||||||
block: hash.startsWith("all") ? "start" : "center",
|
|
||||||
behavior: hash.startsWith("all") ? "smooth" : "auto",
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
window.addEventListener("scroll", removeHash);
|
|
||||||
}, 100);
|
|
||||||
});
|
});
|
||||||
|
window.addEventListener("wheel", removeHash);
|
||||||
}, [hash, removeHash]);
|
}, [hash, removeHash]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const url = new URL(window.location.toString());
|
||||||
|
|
||||||
|
const sortKeyFromUrl = url.searchParams.get("sort");
|
||||||
|
if (sortKeyFromUrl) {
|
||||||
|
_setSortKey(sortKeyFromUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterKeyFromUrl = url.searchParams.get("filter");
|
||||||
|
if (filterKeyFromUrl) {
|
||||||
|
_setKeyword(filterKeyFromUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// hacky but it works for now
|
||||||
|
setTimeout(() => {
|
||||||
|
// don't scroll into view if user got here with back button
|
||||||
|
scrollIntoView();
|
||||||
|
}, 100);
|
||||||
|
}, [setSortKey, setKeyword, scrollIntoView]);
|
||||||
|
|
||||||
const images: GalleryImage[] = React.useMemo(() => {
|
const images: GalleryImage[] = React.useMemo(() => {
|
||||||
const sort =
|
const sort =
|
||||||
sortKey === "date" || sortKey === "datePublished"
|
sortKey === "date"
|
||||||
? R.sort((node1: typeof data["all"]["nodes"][number], node2) =>
|
? R.sort((node1: typeof data["allFile"]["nodes"][number], node2) => {
|
||||||
smartCompareDates(sortKey, node1, node2)
|
const date1 = new Date(
|
||||||
)
|
R.pathOr("", ["fields", "imageMeta", "dateTaken"], node1)
|
||||||
|
);
|
||||||
|
const date2 = new Date(
|
||||||
|
R.pathOr("", ["fields", "imageMeta", "dateTaken"], node2)
|
||||||
|
);
|
||||||
|
return -1 * (date1.getTime() - date2.getTime());
|
||||||
|
})
|
||||||
: R.sort(
|
: R.sort(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
R.descend(R.path<GalleryImage>(SORT_KEYS[sortKey]))
|
||||||
@ -153,7 +157,7 @@ const GalleryPage = ({
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
sort,
|
sort,
|
||||||
filter
|
filter
|
||||||
)(data.all.nodes) as any;
|
)(data.allFile.nodes) as any;
|
||||||
return ret;
|
return ret;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("caught images!", e);
|
console.log("caught images!", e);
|
||||||
@ -161,52 +165,6 @@ const GalleryPage = ({
|
|||||||
}
|
}
|
||||||
}, [data, sortKey, filterKeyword]);
|
}, [data, sortKey, filterKeyword]);
|
||||||
|
|
||||||
const recents = React.useMemo(() => {
|
|
||||||
return R.sort(
|
|
||||||
(left, right) => smartCompareDates("datePublished", left, right),
|
|
||||||
data.recents.nodes
|
|
||||||
);
|
|
||||||
}, [data]);
|
|
||||||
|
|
||||||
const [dbgTags, setDbgTags] = React.useState(false);
|
|
||||||
const [dbgSortKey, setDbgSortKey] = React.useState(false);
|
|
||||||
const [dbgName, setDbgName] = React.useState(false);
|
|
||||||
const dataFn = React.useCallback(
|
|
||||||
(image: GalleryImage): string[] | null => {
|
|
||||||
if (!showDebug) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let data: string[] = [];
|
|
||||||
if (dbgName) {
|
|
||||||
data.push(image.base);
|
|
||||||
}
|
|
||||||
if (dbgSortKey) {
|
|
||||||
switch (sortKey) {
|
|
||||||
case "hue":
|
|
||||||
case "rating": {
|
|
||||||
data.push(R.pathOr("x", SORT_KEYS[sortKey], image));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "date":
|
|
||||||
case "datePublished": {
|
|
||||||
const date = R.pathOr(null, SORT_KEYS[sortKey], image);
|
|
||||||
if (date) {
|
|
||||||
data.push(new Date(date).toLocaleString());
|
|
||||||
} else {
|
|
||||||
data.push("x");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dbgTags) {
|
|
||||||
data.push(image.fields?.imageMeta?.meta?.Keywords?.join(",") ?? "x");
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
[showDebug, sortKey, dbgName, dbgSortKey, dbgTags]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
@ -216,7 +174,6 @@ const GalleryPage = ({
|
|||||||
className="bg-white transition-color"
|
className="bg-white transition-color"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
style={getHelmetSafeBodyStyle(
|
style={getHelmetSafeBodyStyle(
|
||||||
// @ts-ignore shrug
|
|
||||||
getVibrantStyle({
|
getVibrantStyle({
|
||||||
Muted: [0, 0, 0],
|
Muted: [0, 0, 0],
|
||||||
LightMuted: [0, 0, 0],
|
LightMuted: [0, 0, 0],
|
||||||
@ -238,50 +195,8 @@ const GalleryPage = ({
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="gradient pb-6">
|
|
||||||
<div className="px-4 md:px-8 flex items-baseline">
|
|
||||||
<h3 className="mx-2 font-bold" id="recently">
|
|
||||||
Recently published
|
|
||||||
</h3>
|
|
||||||
{sortKey !== "datePublished" && (
|
|
||||||
<Link
|
|
||||||
className="underline cursor-pointer text-gray-500"
|
|
||||||
to="?sort=datePublished#all"
|
|
||||||
>
|
|
||||||
show more
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<MasonryGallery
|
|
||||||
aspectsByBreakpoint={{
|
|
||||||
xs: 3,
|
|
||||||
sm: 3,
|
|
||||||
md: 4,
|
|
||||||
lg: 4,
|
|
||||||
xl: 5,
|
|
||||||
"2xl": 6,
|
|
||||||
"3xl": 8,
|
|
||||||
}}
|
|
||||||
images={recents}
|
|
||||||
linkState={{
|
|
||||||
sortKey: 'datePublished',
|
|
||||||
filterKeyword,
|
|
||||||
}}
|
|
||||||
singleRow
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="px-4 md:px-8 mt-2 pt-2">
|
|
||||||
<h3 className="mx-2 font-bold" id="all">
|
|
||||||
All images
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
<div className="flex flex-col lg:flex-row lg:items-end justify-between px-4 md:px-8 sm:mx-auto">
|
||||||
<KeywordsPicker
|
<KeywordsPicker
|
||||||
getHref={(val, selected) =>
|
|
||||||
selected
|
|
||||||
? getGalleryPageUrl({ keyword: null, sortKey, showDebug }, hash)
|
|
||||||
: getGalleryPageUrl({ keyword: val, sortKey, showDebug }, hash)
|
|
||||||
}
|
|
||||||
keywords={[
|
keywords={[
|
||||||
"Boyce Thompson Arboretum",
|
"Boyce Thompson Arboretum",
|
||||||
"winter",
|
"winter",
|
||||||
@ -291,52 +206,38 @@ const GalleryPage = ({
|
|||||||
"landscape",
|
"landscape",
|
||||||
"flowers",
|
"flowers",
|
||||||
"product",
|
"product",
|
||||||
// "waterfall",
|
"waterfall",
|
||||||
// "fireworks",
|
"fireworks",
|
||||||
// "panoramic",
|
"panoramic",
|
||||||
"Portland Japanese Garden",
|
"Portland Japanese Garden",
|
||||||
// "shoot the light",
|
// "shoot the light",
|
||||||
// "sunset",
|
// "sunset",
|
||||||
]}
|
]}
|
||||||
onPick={onKeywordPick}
|
onChange={setKeyword}
|
||||||
value={filterKeyword}
|
value={filterKeyword}
|
||||||
/>
|
/>
|
||||||
<div className="my-2 mx-2 flex flex-row items-end">
|
<div className="m-2 flex flex-row items-end">
|
||||||
{showDebug && (
|
<div className="border border-black rounded mr-2">
|
||||||
<div className="mr-2">
|
<Switch
|
||||||
<ToggleButton isSelected={dbgName} onChange={setDbgName}>
|
isSelected={showPalette}
|
||||||
name
|
onChange={(val) => setShowPalette(val)}
|
||||||
</ToggleButton>
|
>
|
||||||
<ToggleButton isSelected={dbgSortKey} onChange={setDbgSortKey}>
|
<ColorPalette
|
||||||
sort key
|
UNSAFE_style={{
|
||||||
</ToggleButton>
|
width: "24px",
|
||||||
<ToggleButton isSelected={dbgTags} onChange={setDbgTags}>
|
margin: "0 4px",
|
||||||
tags
|
}}
|
||||||
</ToggleButton>
|
/>
|
||||||
</div>
|
</Switch>
|
||||||
)}
|
|
||||||
<div className="border border-gray-400 rounded mr-2">
|
|
||||||
<Switch
|
|
||||||
isSelected={showPalette}
|
|
||||||
onChange={(val) => setShowPalette(val)}
|
|
||||||
>
|
|
||||||
<ColorPalette
|
|
||||||
UNSAFE_style={{
|
|
||||||
width: "24px",
|
|
||||||
margin: "0 4px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
</div>
|
||||||
<Select
|
<Select
|
||||||
label="Sort by..."
|
label="Sort by..."
|
||||||
// @ts-expect-error React.key, but string is more convenient for the state
|
// @ts-ignore
|
||||||
onSelectionChange={setSortKey}
|
onSelectionChange={setSortKey}
|
||||||
selectedKey={sortKey}
|
selectedKey={sortKey}
|
||||||
>
|
>
|
||||||
<Item key="rating">Curated</Item>
|
<Item key="rating">Curated</Item>
|
||||||
<Item key="datePublished">Date published</Item>
|
<Item key="date">Date</Item>
|
||||||
<Item key="date">Date taken</Item>
|
|
||||||
<Item key="hue">Hue</Item>
|
<Item key="hue">Hue</Item>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@ -352,8 +253,8 @@ const GalleryPage = ({
|
|||||||
"2xl": 6.1,
|
"2xl": 6.1,
|
||||||
"3xl": 8,
|
"3xl": 8,
|
||||||
}}
|
}}
|
||||||
dataFn={dataFn}
|
|
||||||
debugHue={sortKey === "hue_debug"}
|
debugHue={sortKey === "hue_debug"}
|
||||||
|
debugRating={sortKey === "rating" && showDebug}
|
||||||
images={images}
|
images={images}
|
||||||
linkState={{
|
linkState={{
|
||||||
sortKey,
|
sortKey,
|
||||||
@ -367,49 +268,37 @@ const GalleryPage = ({
|
|||||||
|
|
||||||
export const query = graphql`
|
export const query = graphql`
|
||||||
query GalleryPageQuery {
|
query GalleryPageQuery {
|
||||||
recents: allFile(
|
allFile(
|
||||||
filter: { sourceInstanceName: { eq: "gallery" } }
|
|
||||||
sort: { fields: { imageMeta: { datePublished: DESC } } }
|
|
||||||
limit: 10
|
|
||||||
) {
|
|
||||||
...GalleryImageFile
|
|
||||||
}
|
|
||||||
all: allFile(
|
|
||||||
filter: { sourceInstanceName: { eq: "gallery" } }
|
filter: { sourceInstanceName: { eq: "gallery" } }
|
||||||
sort: { fields: { imageMeta: { dateTaken: DESC } } }
|
sort: { fields: { imageMeta: { dateTaken: DESC } } }
|
||||||
) {
|
) {
|
||||||
...GalleryImageFile
|
nodes {
|
||||||
}
|
relativePath
|
||||||
}
|
base
|
||||||
|
childImageSharp {
|
||||||
fragment GalleryImageFile on FileConnection {
|
fluid {
|
||||||
nodes {
|
aspectRatio
|
||||||
base
|
|
||||||
childImageSharp {
|
|
||||||
fluid {
|
|
||||||
aspectRatio
|
|
||||||
}
|
|
||||||
gatsbyImageData(
|
|
||||||
layout: CONSTRAINED
|
|
||||||
height: 550
|
|
||||||
placeholder: DOMINANT_COLOR
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fields {
|
|
||||||
imageMeta {
|
|
||||||
vibrantHue
|
|
||||||
dominantHue
|
|
||||||
dateTaken
|
|
||||||
datePublished
|
|
||||||
meta {
|
|
||||||
Keywords
|
|
||||||
Rating
|
|
||||||
ObjectName
|
|
||||||
CreateDate
|
|
||||||
ModifyDate
|
|
||||||
}
|
}
|
||||||
vibrant {
|
gatsbyImageData(
|
||||||
...VibrantColors
|
layout: CONSTRAINED
|
||||||
|
height: 550
|
||||||
|
placeholder: DOMINANT_COLOR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fields {
|
||||||
|
imageMeta {
|
||||||
|
vibrantHue
|
||||||
|
dominantHue
|
||||||
|
dateTaken
|
||||||
|
meta {
|
||||||
|
Keywords
|
||||||
|
Rating
|
||||||
|
ObjectName
|
||||||
|
}
|
||||||
|
vibrant {
|
||||||
|
# Vibrant
|
||||||
|
...VibrantColors
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,6 @@
|
|||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
:root {
|
|
||||||
/* scroll-behavior: smooth; */
|
|
||||||
}
|
|
||||||
/* .hero * {
|
/* .hero * {
|
||||||
transition: color .2s, background-color .2s;
|
transition: color .2s, background-color .2s;
|
||||||
} */
|
} */
|
||||||
@ -86,15 +83,27 @@
|
|||||||
.gradient {
|
.gradient {
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
hsla(0deg, 0%, 0%, 0%) 95%,
|
hsl(31deg 24% 44%) 0%,
|
||||||
hsla(0deg, 0%, 0%, 10%) 100%
|
hsl(27deg 25% 42%) 7%,
|
||||||
|
hsl(22deg 26% 40%) 14%,
|
||||||
|
hsl(18deg 27% 37%) 21%,
|
||||||
|
hsl(12deg 28% 35%) 29%,
|
||||||
|
hsl(9deg 29% 32%) 36%,
|
||||||
|
hsl(4deg 30% 30%) 43%,
|
||||||
|
hsl(0deg 31% 27%) 50%,
|
||||||
|
hsl(0deg 31% 23%) 57%,
|
||||||
|
hsl(0deg 31% 19%) 64%,
|
||||||
|
hsl(0deg 32% 15%) 71%,
|
||||||
|
hsl(0deg 30% 12%) 79%,
|
||||||
|
hsl(0deg 30% 8%) 86%,
|
||||||
|
hsl(0deg 30% 4%) 93%,
|
||||||
|
hsl(0deg 0% 0%) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-gray-100;
|
@apply bg-gray-100;
|
||||||
overflow: auto;
|
|
||||||
/* @apply bg-black; */
|
/* @apply bg-black; */
|
||||||
/* @apply text-white; */
|
/* @apply text-white; */
|
||||||
}
|
}
|
||||||
|
84
src/utils.ts
84
src/utils.ts
@ -1,23 +1,18 @@
|
|||||||
import React, { useCallback, useRef } from "react";
|
|
||||||
|
|
||||||
import { pathOr } from "ramda";
|
|
||||||
// import kebabCase from 'lodash/kebabCase';
|
// import kebabCase from 'lodash/kebabCase';
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
import { HomepageImage } from "./pages";
|
import { HomepageImage } from "./pages";
|
||||||
import { GalleryImage } from "./pages/photogallery";
|
import { GalleryImage } from "./pages/photogallery";
|
||||||
|
|
||||||
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) =>
|
export const getMeta = <T extends GalleryImage | HomepageImage>(image: T) => image.fields?.imageMeta;
|
||||||
image.fields?.imageMeta;
|
|
||||||
|
|
||||||
export const getName = (image: GalleryImage) =>
|
export const getName = (image: GalleryImage) =>
|
||||||
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
image.fields?.imageMeta?.meta?.ObjectName || image.base;
|
||||||
|
|
||||||
// some pleasing default colors for SSR and initial hydration
|
// some pleasing default colors for SSR and initial hydration
|
||||||
export const getVibrant = (image: GalleryImage | HomepageImage) =>
|
export const getVibrant = (image: GalleryImage | HomepageImage) => getMeta(image)?.vibrant;
|
||||||
getMeta(image)?.vibrant;
|
|
||||||
|
|
||||||
export const hasName = (image: GalleryImage) =>
|
export const hasName = (image: GalleryImage) => Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
||||||
Boolean(image.fields?.imageMeta?.meta?.ObjectName);
|
|
||||||
|
|
||||||
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
export const getAspectRatio = (image: GalleryImage | HomepageImage): number =>
|
||||||
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
image.childImageSharp?.fluid?.aspectRatio ?? 1;
|
||||||
@ -30,10 +25,7 @@ export const getCanonicalSize = (image: GalleryImage) => ({
|
|||||||
export const getRgba = (palette: string[], alpha: number) =>
|
export const getRgba = (palette: string[], alpha: number) =>
|
||||||
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
`rgba(${palette[0]}, ${palette[1]}, ${palette[2]}, ${alpha || 1})`;
|
||||||
|
|
||||||
export const getVibrantStyle = (
|
export const getVibrantStyle = (vibrant: Queries.FileFieldsImageMetaVibrant, screenHeight?: number) => ({
|
||||||
vibrant: Queries.FileFieldsImageMetaVibrant,
|
|
||||||
screenHeight?: number
|
|
||||||
) => ({
|
|
||||||
"--muted": vibrant.Muted,
|
"--muted": vibrant.Muted,
|
||||||
"--dark-muted": vibrant.DarkMuted,
|
"--dark-muted": vibrant.DarkMuted,
|
||||||
"--light-muted": vibrant.LightMuted,
|
"--light-muted": vibrant.LightMuted,
|
||||||
@ -48,12 +40,10 @@ export const getHelmetSafeBodyStyle = (style: React.CSSProperties) => {
|
|||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
return (
|
return Object.keys(style)
|
||||||
Object.keys(style)
|
// @ts-ignore
|
||||||
// @ts-ignore
|
.map((key) => `${key}: ${style[key]};`)
|
||||||
.map((key) => `${key}: ${style[key]};`)
|
.join("");
|
||||||
.join("")
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const gcd = (a: number, b: number): number => {
|
const gcd = (a: number, b: number): number => {
|
||||||
@ -65,9 +55,6 @@ const gcd = (a: number, b: number): number => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getShutterFractionFromExposureTime = (exposureTime: number) => {
|
export const getShutterFractionFromExposureTime = (exposureTime: number) => {
|
||||||
if (exposureTime === 0.3333333333333333) {
|
|
||||||
return "1/3";
|
|
||||||
}
|
|
||||||
if (exposureTime === 0.03333333333333333) {
|
if (exposureTime === 0.03333333333333333) {
|
||||||
return "1/30";
|
return "1/30";
|
||||||
}
|
}
|
||||||
@ -101,14 +88,10 @@ export const getShutterFractionFromExposureTime = (exposureTime: number) => {
|
|||||||
|
|
||||||
interface galleryPageUrlProps {
|
interface galleryPageUrlProps {
|
||||||
keyword: string | null;
|
keyword: string | null;
|
||||||
sortKey: string | null;
|
sortKey: string;
|
||||||
showDebug: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getGalleryPageUrl = (
|
export const getGalleryPageUrl = ({ keyword, sortKey }: galleryPageUrlProps, hash: string) => {
|
||||||
{ keyword, sortKey, showDebug }: galleryPageUrlProps,
|
|
||||||
hash: string
|
|
||||||
) => {
|
|
||||||
const url = new URL(
|
const url = new URL(
|
||||||
`${
|
`${
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
@ -124,55 +107,14 @@ export const getGalleryPageUrl = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sortKey !== undefined) {
|
if (sortKey !== undefined) {
|
||||||
if (sortKey === "rating" || sortKey === null) {
|
if (sortKey === "rating") {
|
||||||
url.searchParams.delete("sort");
|
url.searchParams.delete("sort");
|
||||||
} else {
|
} else {
|
||||||
url.searchParams.set("sort", sortKey);
|
url.searchParams.set("sort", sortKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (showDebug) {
|
|
||||||
url.searchParams.set("debug", "true");
|
|
||||||
}
|
|
||||||
if (hash) {
|
if (hash) {
|
||||||
url.hash = hash;
|
url.hash = hash;
|
||||||
}
|
}
|
||||||
return url.href.toString().replace(url.origin, "");
|
return url.href.toString().replace(url.origin, "");
|
||||||
};
|
};
|
||||||
|
|
||||||
export function compareDates<T>(
|
|
||||||
date_path: readonly string[],
|
|
||||||
left: T,
|
|
||||||
right: T
|
|
||||||
): number {
|
|
||||||
// why tf do my dates have newlines in them?!?!
|
|
||||||
const date1 = new Date(pathOr("", date_path, left).replace(/\s/g, ""));
|
|
||||||
const date2 = new Date(pathOr("", date_path, right).replace(/\s/g, ""));
|
|
||||||
const diff = -1 * (date1.getTime() - date2.getTime());
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a memoized function that will only call the passed function when it hasn't been called for the wait period
|
|
||||||
* @param func The function to be called
|
|
||||||
* @param wait Wait period after function hasn't been called for
|
|
||||||
* @returns A memoized function that is debounced
|
|
||||||
*/
|
|
||||||
export const useDebouncedCallback = (func: Function, wait: number) => {
|
|
||||||
// Use a ref to store the timeout between renders
|
|
||||||
// and prevent changes to it from causing re-renders
|
|
||||||
const timeout = useRef<ReturnType<typeof setTimeout>>();
|
|
||||||
|
|
||||||
return useCallback(
|
|
||||||
(...args: any) => {
|
|
||||||
const later = () => {
|
|
||||||
clearTimeout(timeout.current!);
|
|
||||||
func(...args);
|
|
||||||
};
|
|
||||||
|
|
||||||
clearTimeout(timeout.current ?? undefined);
|
|
||||||
timeout.current = setTimeout(later, wait);
|
|
||||||
},
|
|
||||||
[func, wait]
|
|
||||||
);
|
|
||||||
};
|
|
18
yarn.lock
18
yarn.lock
@ -4560,22 +4560,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/lodash.debounce@npm:^4.0.7":
|
|
||||||
version: 4.0.7
|
|
||||||
resolution: "@types/lodash.debounce@npm:4.0.7"
|
|
||||||
dependencies:
|
|
||||||
"@types/lodash": "*"
|
|
||||||
checksum: e873b2d77f89010876baba3437ef826b17221b98948e00b5590828334a481dea1c8f9d28543210e564adc53199584f42c3cb171f8b6c3614fefc0b4e0888679c
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@types/lodash@npm:*":
|
|
||||||
version: 4.14.191
|
|
||||||
resolution: "@types/lodash@npm:4.14.191"
|
|
||||||
checksum: ba0d5434e10690869f32d5ea49095250157cae502f10d57de0a723fd72229ce6c6a4979576f0f13e0aa9fbe3ce2457bfb9fa7d4ec3d6daba56730a51906d1491
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@types/lodash@npm:^4.14.53":
|
"@types/lodash@npm:^4.14.53":
|
||||||
version: 4.14.170
|
version: 4.14.170
|
||||||
resolution: "@types/lodash@npm:4.14.170"
|
resolution: "@types/lodash@npm:4.14.170"
|
||||||
@ -6480,7 +6464,6 @@ __metadata:
|
|||||||
"@react-spectrum/provider": ^3.6.0
|
"@react-spectrum/provider": ^3.6.0
|
||||||
"@spectrum-icons/workflow": ^4.0.4
|
"@spectrum-icons/workflow": ^4.0.4
|
||||||
"@types/chroma-js": ^2.1.4
|
"@types/chroma-js": ^2.1.4
|
||||||
"@types/lodash.debounce": ^4.0.7
|
|
||||||
"@types/node": ^18.8.3
|
"@types/node": ^18.8.3
|
||||||
"@types/ramda": ^0.28.15
|
"@types/ramda": ^0.28.15
|
||||||
"@types/react": ^18.0.21
|
"@types/react": ^18.0.21
|
||||||
@ -6512,7 +6495,6 @@ __metadata:
|
|||||||
gatsby-source-filesystem: ^5.0.0
|
gatsby-source-filesystem: ^5.0.0
|
||||||
gatsby-transformer-sharp: ^5.0.0
|
gatsby-transformer-sharp: ^5.0.0
|
||||||
kebab-case: ^1.0.1
|
kebab-case: ^1.0.1
|
||||||
lodash.debounce: ^4.0.8
|
|
||||||
node-iptc: ^1.0.5
|
node-iptc: ^1.0.5
|
||||||
node-vibrant: 3.1.6
|
node-vibrant: 3.1.6
|
||||||
postcss: ^8.4.19
|
postcss: ^8.4.19
|
||||||
|
Loading…
x
Reference in New Issue
Block a user