Skip to content

Commit

Permalink
Merge pull request #10 from maxholman/animation
Browse files Browse the repository at this point in the history
feat: add support for view transition api et al
  • Loading branch information
maxholman authored Jun 3, 2024
2 parents ebcd132 + 8a80a57 commit 981156c
Show file tree
Hide file tree
Showing 47 changed files with 4,932 additions and 3,675 deletions.
8 changes: 2 additions & 6 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ module.exports = {
{
files: ['src/examples/**/*', '__tests__/**/*.tsx', '*.config.ts'],
rules: {
'import/no-extraneous-dependencies': [
1,
{
devDependencies: true,
},
],
// allow extraneous DEV deps
'import/no-extraneous-dependencies': 'off',
},
},
],
Expand Down
20 changes: 11 additions & 9 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
name: Deploy

on:
workflow_dispatch: {}
workflow_dispatch:
release:
types: [published]

jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v3
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 18
registry-url: https://registry.npmjs.org/
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
node-version-file: .node-version

- run: make

- run: pnpm publish --access=public --no-git-checks
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
17 changes: 9 additions & 8 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ name: Unit Tests (PR)

on:
pull_request:
branches: ['master']
branches: ['canary', 'master']

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 8
- uses: actions/setup-node@v3
- uses: actions/checkout@v4

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v4
with:
node-version: 18
registry-url: https://registry.npmjs.org/
node-version-file: .node-version
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'

- run: make test
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
3 changes: 0 additions & 3 deletions .npmrc

This file was deleted.

9 changes: 9 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Credit to [@nikparo](https://github.com/nikparo) for "Running React parent effects before child effects"

```
// Sometimes you want to run parent effects before those of the children. E.g. when setting
// something up or binding document event listeners. By passing the effect to the first child it
// will run before any effects by later children.
```

https://gist.github.com/nikparo/33544fe0228dd5aa6f0de8d03e96c378
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ dev: node_modules

.PHONY: types
types: node_modules
pnpm tsc --emitDeclarationOnly --removeComments false
pnpm tsc

build/main.js: node_modules $(SRCS)
build/main.js: node_modules $(SRCS) bundlesize.config.cjs
NODE_ENV=production pnpm vite build
npx bundlesize

Expand Down
6 changes: 3 additions & 3 deletions __tests__/hooks.test.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import type { FC } from 'react';
import { expect, test } from 'vitest';
import type { ExtractRouteParams } from '../lib/types.js';
import { Route, Router, Routes, useRouteParams } from '../src/index.js';
import { namedRoute } from '../src/named-route.js';

const login = namedRoute('/foo/:foo/bar/:bar?');

const EffCee: FC<ExtractRouteParams<typeof login.path>> = () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const EffCee = (_: ExtractRouteParams<typeof login.path>) => {
const match = useRouteParams();

return <pre>{JSON.stringify(match, null, 2)}</pre>;
};

Expand All @@ -26,6 +25,7 @@ test('useMatch', async () => {
>
<Routes>
<Route path={login.path} component={EffCee} />
<Route>if you see this, the test failed</Route>
</Routes>
</Router>,
);
Expand Down
12 changes: 10 additions & 2 deletions __tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { expect, test } from 'vitest';
import { Link, Route, Router, Routes, useLocation } from '../src/index.js';
import { namedRoute } from '../src/named-route.js';

if (!window) {
throw new Error('window is not defined');
}

export const LocationDisplay = () => {
const [location] = useLocation();

Expand All @@ -27,11 +31,15 @@ test('basic', async () => {
</Route>
<Route path="/">
<h1 data-testid="root">You are at the root!</h1>
<Link href={login.build({ origin })}>login</Link>
<Link href={login.build({ origin: window.location.origin })}>
login
</Link>
</Route>
<Route>
<h1>404</h1>
<Link href={root.build({ origin })}>Go to root</Link>
<Link href={root.build({ origin: window.location.origin })}>
Go to root
</Link>
</Route>
</Routes>
</Router>,
Expand Down
4 changes: 1 addition & 3 deletions __tests__/navigate.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ test('programmatic navigation with hooks', async () => {
);

await waitFor(() => {
// global location
// eslint-disable-next-line no-restricted-globals
expect(location.href).toBe('http://localhost:3000/pickles?foo=bar');
expect(window?.location.href).toBe('http://localhost:3000/pickles?foo=bar');

expect(screen.getByTestId('location-display')).toHaveTextContent(
'http://localhost:3000/pickles?foo=bar',
Expand Down
2 changes: 1 addition & 1 deletion __tests__/nested.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ test('wildcard routes + nested', async () => {
const userRoot = namedRoute('/users');
const userView = namedRoute('/users/blah/:userId');

const ComponentWithUserId: FC<{ userId: string }> = ({ userId }) => (
const ComponentWithUserId = ({ userId }: { userId: string }) => (
<>userId = {userId}</>
);

Expand Down
8 changes: 4 additions & 4 deletions __tests__/route.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { useCallback, type FC, type PropsWithChildren } from 'react';
import { useEffect } from 'react';
import { useCallback, useEffect, type FC } from 'react';
import { expect, test, vi } from 'vitest';
import { namedRoute } from '../lib/named-route.js';
import type { RouteComponentProps } from '../lib/types.js';
import {
Route,
Router,
Expand All @@ -14,7 +14,7 @@ import {
const login = namedRoute('/');

test('custom route', async () => {
const CustomRoute = (props: PropsWithChildren<{ path: string }>) => (
const CustomRoute = <T extends string>(props: RouteComponentProps<T>) => (
<Route {...props} />
);

Expand Down Expand Up @@ -53,7 +53,7 @@ test('cancel nav', async () => {
});

test('routes with components/children/paths/no paths', async () => {
const HelloComponent: FC = () => <h1>hello</h1>;
const HelloComponent = () => <h1>hello</h1>;

const { asFragment } = render(
<Router>
Expand Down
10 changes: 6 additions & 4 deletions __tests__/type-inference.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import type { FC } from 'react';
import { expect, test } from 'vitest';
import type { ExtractRouteParams } from '../lib/types.js';
import { Route, Router, Routes } from '../src/index.js';
import { namedRoute } from '../src/named-route.js';

const login = namedRoute('/foo/:foo/bar/:bar?');
const login = namedRoute('/foo/:foo');

const EffCee: FC<ExtractRouteParams<typeof login.path>> = (props) => (
const EffCee = (props: ExtractRouteParams<typeof login.path>) => (
<h1>{props.foo}</h1>
);

Expand All @@ -19,7 +18,10 @@ test('inferred component function props', async () => {
<Route path={login.path}>
<h1>normal</h1>
</Route>
<Route path={login.path} component={(props) => <h1>{props.foo}</h1>} />
<Route
path={login.path}
component={(params) => <h1>{params.foo}</h1>}
/>
<Route path={login.path} component={EffCee} />
<Route>Default route with children</Route>
</Routes>
Expand Down
7 changes: 6 additions & 1 deletion bundlesize.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ module.exports = {
files: [
{
path: './build/*.js',
maxSize: '3.6 kB',
maxSize: '4 kB',
compression: 'brotli',
},
{
path: './build/main.js',
maxSize: '3 kB',
compression: 'brotli',
},
],
Expand Down
50 changes: 49 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand All @@ -10,6 +10,54 @@
flex-direction: column;
height: 100vh;
}

@keyframes fade-in {
from {
opacity: 0;
}
}

@keyframes fade-out {
to {
opacity: 0;
}
}

@keyframes slide-from-bottom {
from {
transform: translateY(50px);
}
}

@keyframes slide-to-top {
to {
transform: translateY(-50px);
}
}

@keyframes slide-to-start {
to {
transform: translateX(-100%);
}
}

@keyframes slide-from-end {
from {
transform: translateX(100%);
}
}

::view-transition-old(pooopies) {
animation:
90ms ease-in both fade-out,
90ms linear both slide-to-start;
}

::view-transition-new(pooopies) {
animation:
90ms ease-in both fade-in,
90ms linear both slide-from-end;
}
</style>
</head>

Expand Down
26 changes: 26 additions & 0 deletions lib/Route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { RouteComponentProps } from './types.js';
import { useRouteMatch } from './use-route-match.js';

export const Route = <TPath extends string>(
props: RouteComponentProps<TPath>,
) => {
const match = useRouteMatch<TPath>();

if (match) {
if (
props &&
'component' in props &&
typeof props.component === 'function'
) {
return props.component(match.params);
}

if ('children' in props) {
return <>{props.children}</>;
}

return <props.component {...match.params} />;
}

return null;
};
Loading

0 comments on commit 981156c

Please sign in to comment.