Skip to content

Instantly share code, notes, and snippets.

View louis-young's full-sized avatar
💻
Probably building something with React 😄

Louis Young louis-young

💻
Probably building something with React 😄
View GitHub Profile
import javascript from "@eslint/js";
import { defineConfig } from "eslint/config";
import { FILE_EXTENSION_GLOB_PATTERNS } from "../constants/glob-patterns";
import { flattenFilesArrays } from "../utilities/flatten-files-arrays";
export const javascriptConfig = defineConfig({
extends: [javascript.configs.recommended],
files: flattenFilesArrays(
FILE_EXTENSION_GLOB_PATTERNS.javascript,
import { expect, test } from "vitest";
import { wordWrapString } from ".";
// characterLimitPerLine = -1 / 5.5
test.each([
{
stringToWordWrap: "Hello World",
characterLimitPerLine: 20,
expectedWordWrappedString: "Hello World",
@louis-young
louis-young / index.tsx
Created December 7, 2023 12:14
Generic select input React component
import { type ChangeEvent, useState } from "react";
type SelectInputOption<TOptionValue> = {
label: string;
value: TOptionValue;
};
interface SelectInputProps<TOptionValue> {
options: Array<SelectInputOption<TOptionValue>>;
selectedValue: TOptionValue;
@louis-young
louis-young / formatter.js
Created November 21, 2023 08:35
ESLint formatter
module.exports = (results) => {
const byRuleId = results.reduce((map, current) => {
for (const { column, line, ruleId } of current.messages) {
if (!map[ruleId]) {
map[ruleId] = [];
}
const occurrence = `${current.filePath}:${line}:${column}`;
map[ruleId].push(occurrence);
}
@louis-young
louis-young / index.ts
Last active September 6, 2023 16:53
C# LINQ method analogs in TypeScript
const singleOrDefault = <TElement, TDefaultValue>(
array: ReadonlyArray<TElement>,
predicate: (element: TElement) => boolean,
defaultValue: TDefaultValue
): TElement | TDefaultValue => {
if (array.length === 0) {
throw new Error("The source sequence is empty.");
}
const element = array.find(predicate);
@louis-young
louis-young / index.ts
Last active July 25, 2023 21:24
Lunchtime LINQ challenges
/**
* https://markheath.net/post/lunchtime-linq-challenge
*/
interface GetSecondsFromMinutesAndSecondsParameters {
minutes: number;
seconds: number;
}
const getSecondsFromMinutesAndSeconds = ({
@louis-young
louis-young / index.tsx
Created July 19, 2023 15:01
Asynchronous React component
import type { ReactNode } from "react";
interface AsynchronousComponentProps<TData> {
children: (data: NonNullable<TData>) => ReactNode;
data: TData;
isLoading: boolean;
loadingFallback: ReactNode;
hasError: boolean;
errorFallback: ReactNode;
}
@louis-young
louis-young / index.ts
Last active May 25, 2023 16:32
useDebouncedValue
import { useEffect, useState } from "react";
export const useDebouncedValue = <TValue>(value: TValue, delay: number) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(value);
}, delay);
@louis-young
louis-young / index.tsx
Created March 22, 2023 14:08
Infinite Scroll
import { useRef } from "react";
import { useIntersectionObserver } from "../../hooks/useIntersectionObserver";
import type { InfiniteScrollProps } from "./types";
export const InfiniteScroll = ({
loadMoreFunction,
isLoadingMore,
loadingMoreMessage,
hasLoadedEverything,
loadedEverythingMessage,
@louis-young
louis-young / index.tsx
Created March 22, 2023 14:07
useIntersectionObserver
import { useEffect } from "react";
import type { UseIntersectionObserverParameters } from "./types";
export const useIntersectionObserver = ({
observableRef,
callback,
options,
}: UseIntersectionObserverParameters) => {
useEffect(() => {
const intersectionObserver = new IntersectionObserver(