diff --git a/.prettierrc b/.prettierrc index b2095be..494de5f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,12 @@ { "semi": false, - "singleQuote": true + "singleQuote": true, + "overrides": [ + { + "files": "snippets/snippets/**/*.ts", + "options": { + "printWidth": 45 + } + } + ] } diff --git a/package.json b/package.json index 155ad97..295fe46 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,17 @@ "build": "next build && next export", "start": "next start", "tsc": "tsc", + "ts-node": "ts-node", "eslint": "eslint --ext .js,.ts,.tsx .", "eslint:fix": "eslint --ext .js,.ts,.tsx --fix .", - "svgr": "svgr --ext tsx --no-svgo --no-dimensions -d ." + "svgr": "svgr --ext tsx --no-svgo --no-dimensions -d .", + "snippets": "runSnippet snippets/bin/generateSnippetsBundle.ts", + "runSnippet": "ts-node --project tsconfig.snippets.json" }, "devDependencies": { "@svgr/cli": "^4.3.3", "@types/color": "^3.0.0", + "@types/glob": "^7.1.1", "@types/luxon": "^1.15.2", "@types/node": "^12.12.7", "@types/prettier": "^1.18.3", @@ -34,13 +38,16 @@ "@typescript-eslint/parser": "^2.7.0", "babel-eslint": "^10.0.3", "babel-plugin-emotion": "^10.0.23", + "chokidar": "^3.3.0", "eslint": "^6.5.1", "eslint-config-prettier": "^6.4.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-prettier": "^3.1.1", "eslint-plugin-react": "^7.16.0", "eslint-plugin-react-hooks": "2.2.0", + "glob": "^7.1.6", "prettier": "^1.19.1", + "ts-node": "^8.5.2", "typescript": "^3.7.2" } } diff --git a/snippets/.eslintrc.js b/snippets/.eslintrc.js new file mode 100644 index 0000000..8fd5c4f --- /dev/null +++ b/snippets/.eslintrc.js @@ -0,0 +1,9 @@ +const config = require('../.eslintrc') + +module.exports = { + ...config, + parserOptions: { + project: './snippets/tsconfig.json' + }, + root: true +} diff --git a/snippets/bin/generateSnippetsBundle.ts b/snippets/bin/generateSnippetsBundle.ts new file mode 100644 index 0000000..3caeae1 --- /dev/null +++ b/snippets/bin/generateSnippetsBundle.ts @@ -0,0 +1,28 @@ +const glob = require('glob') +const fs = require('fs') +const chokidar = require('chokidar') + +const regenerate = () => { + glob('./snippets/snippets/**/*.ts', (_: any, files: readonly string[]) => { + const result = files + .map(file => { + const contents = fs.readFileSync(file, 'utf8') + return `export const ${file + .replace(/\.\/snippets\/snippets\/\w+\//, '') + .replace(/\.ts/, '')} = \`${contents.trim()}\`` + }) + .join('\n\n') + + fs.writeFile('./src/lib/snippets.ts', `${result}\n`, (err: any) => { + if (err) { + throw err + } + console.log('snippets generated') + }) + }) +} + +regenerate() +chokidar.watch('./snippets/snippets/**/*.ts').on('change', () => { + regenerate() +}) diff --git a/snippets/snippets/generics/cbeq.ts b/snippets/snippets/generics/cbeq.ts new file mode 100644 index 0000000..9e8f346 --- /dev/null +++ b/snippets/snippets/generics/cbeq.ts @@ -0,0 +1,7 @@ +const { getState, setState } = createState() + +setState(1) +console.log(getState()) + +setState(2) +console.log(getState()) diff --git a/snippets/snippets/generics/cupt.ts b/snippets/snippets/generics/cupt.ts new file mode 100644 index 0000000..6773316 --- /dev/null +++ b/snippets/snippets/generics/cupt.ts @@ -0,0 +1,16 @@ +function createState() { + let state: number + + function getState() { + return state + } + + function setState(x: number) { + state = x + } + + return { + getState, + setState + } +} diff --git a/snippets/snippets/generics/kiyi.ts b/snippets/snippets/generics/kiyi.ts new file mode 100644 index 0000000..572326f --- /dev/null +++ b/snippets/snippets/generics/kiyi.ts @@ -0,0 +1,5 @@ +// Confused by generics code like this? +function getProperty( + obj: T, + key: K +) diff --git a/snippets/snippets/generics/udpv.ts b/snippets/snippets/generics/udpv.ts new file mode 100644 index 0000000..e5e5dc7 --- /dev/null +++ b/snippets/snippets/generics/udpv.ts @@ -0,0 +1,24 @@ +function createState() { + let state: number + + function getState() { + return state + } + + function setState(x: number) { + state = x + } + + return { + getState, + setState + } +} + +const { getState, setState } = createState() + +setState(1) +console.log(getState()) + +setState(2) +console.log(getState()) diff --git a/snippets/tsconfig.json b/snippets/tsconfig.json new file mode 100644 index 0000000..74d83a2 --- /dev/null +++ b/snippets/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.snippets.json" +} diff --git a/src/components/ButtonWithTouchActiveStates.tsx b/src/components/ButtonWithTouchActiveStates.tsx new file mode 100644 index 0000000..851841c --- /dev/null +++ b/src/components/ButtonWithTouchActiveStates.tsx @@ -0,0 +1,43 @@ +/** @jsx jsx */ +import { css, jsx } from '@emotion/core' +import { useState } from 'react' + +type ButtonWithTouchActiveStatesProps< + T = JSX.IntrinsicElements['button'] +> = T & { + activeBackgroundColor: string +} + +const ButtonWithTouchActiveStates = ({ + activeBackgroundColor, + ...props +}: ButtonWithTouchActiveStatesProps) => { + const [isActive, setIsActive] = useState(false) + const activate = () => { + if (!props.disabled) { + // NOTE: Originally tried to call the callback here and do e.preventDefault() + // to prevent mouse click event from happening, so that callback fires + // on tap start instead of on tap end, but that was buggy so ended up removing. + setIsActive(true) + } + } + const deactivate = () => { + setIsActive(false) + } + return ( +