Skip to content

Instantly share code, notes, and snippets.

View jeremy-code's full-sized avatar

Jeremy Nguyen jeremy-code

View GitHub Profile
@jeremy-code
jeremy-code / tsconfig.json
Created April 20, 2024 23:32
TSConfig Cheat Sheet with Comments
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"moduleDetection": "force",
/* Modules */
@jeremy-code
jeremy-code / getUser.ts
Created March 6, 2024 03:48
getUser.ts for react-oidc-context
import { User } from "oidc-client-ts";
const { VITE_OIDC_AUTHORITY, VITE_OIDC_CLIENT_ID } = import.meta.env;
const AUTH_KEY = `oidc.user:${VITE_OIDC_AUTHORITY}:${VITE_OIDC_CLIENT_ID}`;
// Get the user from local storage (used for API requests where hooks are not available)
export const getUser = () => {
const storageString = localStorage.getItem(AUTH_KEY);
if (!storageString) return null;
@jeremy-code
jeremy-code / colors.ts
Created March 6, 2024 03:30
colors (RGB, hexToRgb, rgbToHex)
type RGB = {
r: number;
g: number;
b: number;
};
export const hexToRgb = (hex: string): RGB => {
const bigint = parseInt(hex.slice(1), 16);
return {
@jeremy-code
jeremy-code / debounce.ts
Created March 6, 2024 03:08
debounce.ts
export function debounce<T extends (...args: Parameters<T>) => ReturnType<T>>(
callback: T,
wait: number,
immediate?: boolean
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout | undefined;
return function (this: ThisParameterType<T>, ...args: Parameters<T>): void {
const later = () => {
timeout = undefined;
@jeremy-code
jeremy-code / parseFormData.ts
Created March 6, 2024 03:06
parseFormData.ts
export const parseFormData = (formData: FormData) =>
Array.from(formData.entries()).reduce(
(acc, [k, v]) => {
if (!acc[k]) {
const values = formData.getAll(k);
acc[k] = values.length > 1 ? values : v;
}
return acc;
},
{} as Record<string, FormDataEntryValue | FormDataEntryValue[]>
@jeremy-code
jeremy-code / formatBytes.ts
Created March 6, 2024 03:03
formatBytes.ts, format bytes
export const formatBytes = (bytes: number, options?: Intl.NumberFormatOptions) => {
/**
* Per {@link https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers},
* these are the valid units for the "unit" style. Since each unit multiple is
* considered a separate unit, we have to manually determine the appropriate unit
* and corresponding value, otherwise we get formatting such as "1 BB" instead of
* "1 GB".
*/
const units = ["byte", "kilobyte", "megabyte", "gigabyte", "terabyte", "petabyte"];
if (!bytes || bytes <= 0) return `0 ${units[0]}s`;
@jeremy-code
jeremy-code / useProgressStore.tsx
Created March 6, 2024 02:58
useProgressStore hook, get progress from a ky event handler
// when you create ky instance, set onDownloadProgress: progressStore.setSnapshot,
import { useSyncExternalStore } from "react";
import type { DownloadProgress } from "ky";
export const shallowCompare = <T extends Record<string, unknown>>(obj1: T, obj2: T) => {
if (Object.is(obj1, obj2)) return true;
if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) return false;
import React, { useCallback, useEffect, useRef } from "react";
import { useForm } from "react-hook-form";
import useScript from "../hooks/useScript";
type LocationFormData = {
location: string;
};
const AutocompleteInput = () => {
@jeremy-code
jeremy-code / AutcompleteInput.tsx
Created August 7, 2022 20:53
React Google Autocomplete Input
import React, { useCallback, useEffect, useRef } from "react";
import useScript from "../hooks/useScript";
const AutocompleteInput = () => {
// Load the Google Maps API script asynchronously
const status = useScript(
`https://maps.googleapis.com/maps/api/js?key=${
import.meta.env.VITE_GOOGLE_MAPS_API_KEY
}&libraries=places`
@jeremy-code
jeremy-code / useScript.tsx
Last active August 7, 2022 20:44
React useScript hook
import { useEffect, useState } from "react";
type ScriptStatus = "idle" | "loading" | "ready" | "error";
type ScriptType = HTMLScriptElement | null;
function useScript(src: string): ScriptStatus {
const [status, setStatus] = useState<ScriptStatus>(src ? "loading" : "idle");
useEffect(() => {
// Fetch existing script element by src