Skip to content

Instantly share code, notes, and snippets.

View jossmac's full-sized avatar
Building Keystatic

Joss Mackison jossmac

Building Keystatic
View GitHub Profile
@jossmac
jossmac / pluralize.ts
Created November 5, 2025 22:35
Returns the count and appropriate plural or singular form of a term.
/**
* Returns the count and appropriate plural or singular form of a term.
*
* @example
* pluralize(0, 'wallet'); // '0 wallets'
* pluralize(1, 'wallet'); // '1 wallet'
* pluralize(2, 'wallet'); // '2 wallets'
* pluralize(1, ['person', 'people']); // '1 person'
* pluralize(2, ['person', 'people']); // '2 people'
* pluralize(1, ['person', 'people'], false); // 'person'
@jossmac
jossmac / styleVars.ts
Created October 13, 2025 21:15
CSS custom properties in TS/React `style` attribute. Alternative to module declarations, or comment directives.
import type { CSSProperties } from 'react';
type StyleVars = Record<
`--${string}`,
string | number | boolean | undefined | null
>;
/**
* Type casting identity function. Maintains the autocompletion and type safety
* of `CSSProperties`, while allowing the addition of CSS variables.
@jossmac
jossmac / shape-paths.ts
Last active August 20, 2025 06:11
Generate the path data for shapes using familiar e.g. `circle` and `rect` syntax.
const DRAW_DIRECTION = ["clockwise", "anti-clockwise"] as const;
/**
* Generate a complex path string, using familiar SVG shape (`<circle>`,
* `<rect>`, etc.) syntax.
*
* @param data An array of shape objects.
* @param evenodd Alternate drawing direction for each path. When multiple paths are combined into a single string of path data, this will influence whether the paths are additive or subtractive.
* @returns A string of SVG path data representing all shapes.
*
@jossmac
jossmac / partial-application.js
Created August 8, 2019 07:16
Fixing a number of arguments to a function, producing another function of smaller arity
const partialApply = (fn, ...fixedArgs) => {
return (...remainingArgs) => fn(...fixedArgs.concat(...remainingArgs));
};
const add = (a, b) => a + b;
const add10 = partialApply(add, 10);
console.log(add10(5)) // 15
@jossmac
jossmac / medium_article_context-toast_consumer_extended.jsx
Last active November 1, 2018 03:21
Pseudo code for a consumer component
import React from 'react';
import { ToastContext } from './Provider';
export const ToastConsumer = ({ children }) => (
<ToastContext.Consumer>
{context => children(context)}
</ToastContext.Consumer>
);
// Higher-Order Component
@jossmac
jossmac / medium_article_context-toast_consumer.jsx
Last active November 1, 2018 03:07
Pseudo code for a consumer component
import React from 'react';
import { ToastContext } from './Provider';
export const ToastConsumer = ({ children }) => (
<ToastContext.Consumer>
{context => children(context)}
</ToastContext.Consumer>
);
@jossmac
jossmac / medium_article_context-toast_provider.jsx
Last active November 1, 2018 03:02
Pseudo code for a provider component
import React from 'react';
import Renderer from './Renderer';
export const ToastContext = React.createContext();
export class ToastProvider extends React.Component {
state = { toasts: [] }
add = (content) => {
this.setState(...);
@jossmac
jossmac / medium_article_context-toast_class.jsx
Last active November 5, 2018 00:59
Store class with subscribers
export default class Store {
listeners = []
store = []
add = (data) => {
const id = uniqueId()
const item = { id, data }
this.store.push(item)
this.publish()
}
@jossmac
jossmac / mergeObjects.js
Created October 26, 2018 03:06
Spreading objects for styles feels messy, handle it with this function instead...
// probably unnecessary but...
const merge = (...args) => args.reduce((obj, val) => ({ ...obj, ...val }), {});
const combined = merge(
{ background: 'red', padding: 20 },
{ color: 'blue' },
{ color: 'white' },
);
console.log(combined); // { background: 'red', padding: 20, color: 'white' }
@jossmac
jossmac / not.js
Created October 26, 2018 02:41
Negation function for less verbose code
function not(predicate) {
return function negate(...args) {
return !predicate(...args);
}
}
// Usage
// ==============================
function longEnough(str) {