Skip to content

Instantly share code, notes, and snippets.

View samselikoff's full-sized avatar

Sam Selikoff samselikoff

View GitHub Profile
@samselikoff
samselikoff / brush_redraw_vertical_axis.js
Created September 5, 2013 07:44
Brush function for d3.js that redraws the vertical axis based on the range of data currently shown
function brush() {
// Use x.domain to filter the data, then find the max and min duration of this new set, and set y.domain to that
x.domain(brush.empty() ? x2.domain() : brush.extent());
var dataFiltered = data.filter(function(d, i) {
if ( (d.date >= x.domain()[0]) && (d.date <= x.domain()[1]) ) {
return this;
}
})
var buildersFiltered = color.domain().map(function(name) {
return {
@samselikoff
samselikoff / cloudSettings
Last active March 18, 2026 18:23
Visual Studio Code Settings Sync Gist
{"lastUpload":"2020-05-01T19:06:41.818Z","extensionVersion":"v3.4.3"}
import { ReactNode, useLayoutEffect, useRef } from 'react';
const keyframes = `
@keyframes spinner {
0% { opacity: 1; }
100% { opacity: 0; }
}
`;
export default function Spinner({
@samselikoff
samselikoff / future-proof.md
Last active August 2, 2025 18:41
Future-proofing your Ember 1.x code

This post is also on my blog, since Gist doesn't support @ notifications.


Components are taking center stage in Ember 2.0. Here are some things you can do today to make the transition as smooth as possible:

  • Use Ember CLI
  • In general, replace views + controllers with components
  • Only use controllers at the top-level for receiving data from the route, and use Ember.Controller instead of Ember.ArrayController or Ember.ObjectController
  • Fetch data in your route, and set it as normal properties on your top-level controller. Export an Ember.Controller, otherwise a proxy will be generated. You can use Ember.RSVP.hash to simulate setting normal props on your controller.
@samselikoff
samselikoff / chart-with-d3.jsx
Last active July 7, 2025 06:54
Diff from "Building an Animated Line Chart with d3, React and Framer Motion" https://www.youtube.com/watch?v=kPbRDn5Fg0Y
import * as d3 from "d3";
import {
eachMonthOfInterval,
endOfMonth,
format,
isSameMonth,
parseISO,
startOfMonth,
} from "date-fns";
import useMeasure from "react-use-measure";
@samselikoff
samselikoff / tailwind.config.js
Created April 16, 2021 15:57
Firefox plugin for Tailwind CSS. Add styles that target Firefox browser only.
const plugin = require("tailwindcss/plugin");
module.exports = {
mode: "jit",
purge: {
content: ["./src/**/*.{js,ts,jsx,tsx,mdx,vue}"],
},
theme: { extend: {} },
variants: {},
plugins: [
@samselikoff
samselikoff / settings.json
Last active February 20, 2025 15:40
Tweaked Dracula theme for VSCode
{
"diffEditor.renderSideBySide": true,
"editor.fontSize": 14,
"editor.lineHeight": 22,
"editor.tabSize": 2,
"editor.matchBrackets": "never",
"editor.cursorBlinking": "solid",
"editor.selectionHighlight": false,
"editor.occurrencesHighlight": "off",
"editor.scrollbar.horizontal": "hidden",
[
{
"key": "ctrl+k",
"command": "editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+up",
"command": "-editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"

Remix's useFetcher doesn't return a Promise for any of its methods (like fetcher.submit()) because Remix doesn't want you to explicitly await anything so they can handle things like cancellation for you. Instead, they recommend adding a useEffect and performing whatever logic you need to after the fetcher is in a particular state.

I found using an effect to run some logic after a submission to be too indirect, and there seem to be plenty of cases where you want to submit a form and then perform some other work on the client (sometimes async, like requesting the user's permission for their location), and I'd rather just do that after a submission in the event handler rather than an effect.

So here's a proof of concept hook that wraps Remix's useFetcher and returns a version of submit that is a promise, and resolves with the data from the action:

function useFetcherWithPromise() {
  let resolveRef = useRef();
  let promiseRef = useRef();

Version 1

import { useActionState } from "react";

async function addToCart(itemId) {
  'use server'

  if (db.add(itemId)) {
    return "success"