Skip to content

Instantly share code, notes, and snippets.

@ngbrown
ngbrown / entry.server.tsx
Last active August 30, 2024 07:25
Populate Links in Remix for Cloudflare 103 hints
/**
* By default, Remix will handle generating the HTTP Response for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.server
*/
import type { AppLoadContext, EntryContext } from "@remix-run/cloudflare";
import { RemixServer } from "@remix-run/react";
import { isbot } from "isbot";
import { renderToReadableStream } from "react-dom/server";
@ngbrown
ngbrown / nav.tsx
Last active August 6, 2024 07:09
Nav for Remix (and React Router) - Use to drive which component has the active link in a menu
import React from "react";
import type { LinkProps } from "@remix-run/react";
import { stripBasename } from "@remix-run/router";
import {
UNSAFE_DataRouterStateContext as DataRouterStateContext,
UNSAFE_NavigationContext as NavigationContext,
useLocation,
useResolvedPath,
@ngbrown
ngbrown / SemaphoreSlimExtensions.cs
Created May 21, 2024 15:48
SemaphoreSlimExtensions
public static class SemaphoreSlimExtensions
{
/// <summary>
/// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>. Returns an <see cref="IDisposable"/> to be used in <c>using</c>.
/// </summary>
/// <param name="semaphore">A <see cref="SemaphoreSlim"/> to lock.</param>
/// <returns>An <see cref="IDisposable"/> that will release the <see cref="SemaphoreSlim"/> when disposed.</returns>
public static IDisposable Lock(this SemaphoreSlim semaphore)
{
semaphore.Wait();
@ngbrown
ngbrown / Remix.xml
Last active April 9, 2024 20:50
WebStorm Live Template for Remix
<templateSet group="Remix">
<template name="useFetcher" value="const $fetcher$ = useFetcher();" description="const fetcher = useFetcher()" toReformat="true" toShortenFQNames="true" useStaticImport="true">
<variable name="fetcher" expression="" defaultValue="&quot;fetcher&quot;" alwaysStopAt="true" />
<context>
<option name="JS_CLASS_MEMBER_STATEMENT" value="false" />
<option name="JS_STATEMENT" value="true" />
<option name="TS_CLASS_MEMBER_STATEMENT" value="false" />
<option name="TS_STATEMENT" value="true" />
</context>
</template>
@ngbrown
ngbrown / svg-path-builder.ts
Last active April 14, 2024 18:06
SVG Path Builder (TypeScript)
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands
// https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
// M moveto (x y)+
// Z closepath (none)
// L lineto (x y)+
// H horizontal lineto x+
// V vertical lineto y+
// C curveto (x1 y1 x2 y2 x y)+
// S smooth curveto (x2 y2 x y)+
// Q quadratic Bézier curveto (x1 y1 x y)+
@ngbrown
ngbrown / download-git-powershell.md
Created January 10, 2024 17:44
Downloading Git for Windows PowerShell

To download Git with PowerShell:

Get most recent version URL from https://git-scm.com/download/win

cd "${env:USERPROFILE}\Downloads"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
$ProgressPreference = 'SilentlyContinue';Invoke-WebRequest -Uri https://github.com/git-for-windows/git/releases/download/v2.43.0.windows.1/Git-2.43.0-64-bit.exe -OutFile Git-2.43.0-64-bit.exe
@ngbrown
ngbrown / client-only.tsx
Created December 27, 2023 18:58
Remix Client Only Component
import React, { ComponentType, lazy, Suspense } from "react";
export function ClientOnly({
fallback,
component,
}: {
fallback: React.ReactElement;
component: Promise<{ default: ComponentType<any> }>;
}) {
const LazyComponent = lazy(() => component);
@ngbrown
ngbrown / generate-fontawesome-icons.js
Created December 21, 2023 02:42
Generate TypeScript files containing Font Awsome Icons from kit metadata
#!/usr/bin/env node
/* eslint-env node */
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
async function main() {
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@ngbrown
ngbrown / use-dynamic-throttle.ts
Last active August 19, 2023 17:10
useDynamicThrottle React hook
import { useCallback, useEffect, useRef, useState } from "react";
/**
* Returns a throttled version of the value and a function to release the next update, which may occur immediately or
* on the next value change.
*
* This can be used to keep the interface responsive when you have values that are changing too fast for async processes to keep up.
* @param value The value that is going to be throttled
*/
export function useDynamicThrottle<T>(
@ngbrown
ngbrown / uplot-react.tsx
Last active August 11, 2023 08:47
Updated uplot-react
// Adapted from https://github.com/skalinichev/uplot-wrappers
// MIT license
import type { JSX } from "react";
import React, { useCallback, useEffect, useRef } from "react";
import uPlot from "uplot";
import { dataMatch, optionsUpdateState } from "./uplot-wrappers-common.js";
export default function UplotReact({