@remix-run/cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/bootstrap/.agents/skills/remix/SKILL.md +501 -0
- package/bootstrap/.agents/skills/remix/references/animate-elements.md +195 -0
- package/bootstrap/.agents/skills/remix/references/assets-and-browser-modules.md +122 -0
- package/bootstrap/.agents/skills/remix/references/auth-and-sessions.md +420 -0
- package/bootstrap/.agents/skills/remix/references/component-model.md +282 -0
- package/bootstrap/.agents/skills/remix/references/create-mixins.md +158 -0
- package/bootstrap/.agents/skills/remix/references/data-and-validation.md +363 -0
- package/bootstrap/.agents/skills/remix/references/hydration-frames-navigation.md +297 -0
- package/bootstrap/.agents/skills/remix/references/middleware-and-server.md +243 -0
- package/bootstrap/.agents/skills/remix/references/mixins-styling-events.md +213 -0
- package/bootstrap/.agents/skills/remix/references/routing-and-controllers.md +324 -0
- package/bootstrap/.agents/skills/remix/references/testing-patterns.md +156 -0
- package/bootstrap/AGENTS.md +4 -0
- package/bootstrap/app/assets/entry.ts +19 -0
- package/bootstrap/app/assets.ts +18 -0
- package/bootstrap/app/controllers/auth.tsx +2 -2
- package/bootstrap/app/controllers/home.tsx +3 -18
- package/bootstrap/app/router.ts +6 -0
- package/bootstrap/app/routes.ts +2 -1
- package/bootstrap/app/ui/document.tsx +6 -1
- package/bootstrap/app/ui/prompt-button.tsx +162 -0
- package/bootstrap/app/ui/scaffold-home-page.tsx +526 -0
- package/bootstrap/app/utils/render.tsx +22 -3
- package/bootstrap/server.ts +13 -13
- package/bootstrap/tsconfig.json +0 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +7 -10
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +9 -33
- package/dist/lib/commands/test.d.ts +1 -1
- package/dist/lib/commands/test.d.ts.map +1 -1
- package/dist/lib/commands/test.js +8 -4
- package/dist/lib/completion.d.ts.map +1 -1
- package/dist/lib/completion.js +3 -101
- package/dist/lib/errors.d.ts +0 -6
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +0 -11
- package/package.json +3 -4
- package/src/lib/cli.ts +7 -11
- package/src/lib/commands/help.ts +9 -43
- package/src/lib/commands/test.ts +10 -4
- package/src/lib/completion.ts +3 -146
- package/src/lib/errors.ts +0 -12
- package/dist/lib/commands/skills.d.ts +0 -6
- package/dist/lib/commands/skills.d.ts.map +0 -1
- package/dist/lib/commands/skills.js +0 -222
- package/dist/lib/skills-cache.d.ts +0 -19
- package/dist/lib/skills-cache.d.ts.map +0 -1
- package/dist/lib/skills-cache.js +0 -89
- package/dist/lib/skills.d.ts +0 -30
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js +0 -441
- package/src/lib/commands/skills.ts +0 -306
- package/src/lib/skills-cache.ts +0 -140
- package/src/lib/skills.ts +0 -706
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Animating Elements
|
|
2
|
+
|
|
3
|
+
## What This Covers
|
|
4
|
+
|
|
5
|
+
How to animate insertion, removal, and layout changes of elements. Read this when the task
|
|
6
|
+
involves:
|
|
7
|
+
|
|
8
|
+
- Adding entrance, exit, or shared-layout transitions to UI
|
|
9
|
+
- Choosing between spring physics (`spring(...)`) and time-based easing (`tween`)
|
|
10
|
+
- Coordinating CSS transitions with the same easing as JS animations
|
|
11
|
+
- Imperative animation loops via `requestAnimationFrame`
|
|
12
|
+
|
|
13
|
+
Import animation APIs from `remix/ui/animation`. For the smaller set of animation helpers that
|
|
14
|
+
show up alongside other mixins, see `mixins-styling-events.md`.
|
|
15
|
+
|
|
16
|
+
## Animation Mixins
|
|
17
|
+
|
|
18
|
+
### `animateEntrance(config)`
|
|
19
|
+
|
|
20
|
+
Animates an element when inserted. Config specifies the **starting** style the element animates
|
|
21
|
+
**from**:
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
<div
|
|
25
|
+
mix={animateEntrance({
|
|
26
|
+
opacity: 0,
|
|
27
|
+
transform: 'translateY(8px)',
|
|
28
|
+
...spring('smooth'),
|
|
29
|
+
})}
|
|
30
|
+
/>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### `animateExit(config)`
|
|
34
|
+
|
|
35
|
+
Animates an element when removed. Config specifies the **ending** style the element animates
|
|
36
|
+
**to**. The element stays in the DOM until the animation completes:
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
{
|
|
40
|
+
isVisible && (
|
|
41
|
+
<div
|
|
42
|
+
key="panel"
|
|
43
|
+
mix={[
|
|
44
|
+
animateEntrance({ opacity: 0, transform: 'scale(0.98)', ...spring('smooth') }),
|
|
45
|
+
animateExit({ opacity: 0, duration: 120, easing: 'ease-in' }),
|
|
46
|
+
]}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### `animateLayout(config?)`
|
|
53
|
+
|
|
54
|
+
Animates layout changes (position/size) using FLIP-style transforms:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
{
|
|
58
|
+
items.map((item) => (
|
|
59
|
+
<li key={item.id} mix={animateLayout({ ...spring({ duration: 500, bounce: 0.2 }) })} />
|
|
60
|
+
))
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Options: `duration` (default 200ms), `easing` (default spring snappy), `size` (default true —
|
|
65
|
+
include scale projection for size changes).
|
|
66
|
+
|
|
67
|
+
### Combining mixins
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
<div
|
|
71
|
+
key="card"
|
|
72
|
+
mix={[
|
|
73
|
+
animateEntrance({ opacity: 0, transform: 'scale(0.95)', ...spring('snappy') }),
|
|
74
|
+
animateExit({ opacity: 0, transform: 'scale(0.98)', duration: 120, easing: 'ease-in' }),
|
|
75
|
+
animateLayout({ duration: 220, easing: 'ease-out' }),
|
|
76
|
+
]}
|
|
77
|
+
/>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Shared-layout swap
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<div mix={css({ display: 'grid', '& > *': { gridArea: '1 / 1' } })}>
|
|
84
|
+
{stateA ? (
|
|
85
|
+
<div key="a" mix={[animateEntrance({ opacity: 0 }), animateExit({ opacity: 0 })]} />
|
|
86
|
+
) : (
|
|
87
|
+
<div key="b" mix={[animateEntrance({ opacity: 0 }), animateExit({ opacity: 0 })]} />
|
|
88
|
+
)}
|
|
89
|
+
</div>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Spring API
|
|
93
|
+
|
|
94
|
+
Physics-based spring animation. Returns a `SpringIterator` with `duration`, `easing`, and
|
|
95
|
+
`toString()` for CSS.
|
|
96
|
+
|
|
97
|
+
### Presets
|
|
98
|
+
|
|
99
|
+
| Preset | Bounce | Duration | Character |
|
|
100
|
+
| -------- | ------ | -------- | --------------------------- |
|
|
101
|
+
| `smooth` | -0.3 | 400ms | Overdamped, no overshoot |
|
|
102
|
+
| `snappy` | 0 | 200ms | Critically damped, quick |
|
|
103
|
+
| `bouncy` | 0.3 | 400ms | Underdamped, visible bounce |
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
spring('bouncy')
|
|
107
|
+
spring('snappy')
|
|
108
|
+
spring('smooth')
|
|
109
|
+
spring('bouncy', { duration: 300 }) // override duration
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Custom spring
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
spring({ duration: 500, bounce: 0.3 })
|
|
116
|
+
spring({ duration: 500, bounce: 0.3, velocity: 2 }) // continue momentum from gesture
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Spread into animation mixins
|
|
120
|
+
|
|
121
|
+
Spreading a spring gives both `duration` and `easing`:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
animateEntrance({ opacity: 0, ...spring('bouncy') })
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### CSS transitions
|
|
128
|
+
|
|
129
|
+
The iterator stringifies to `"550ms linear(...)"`:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
css({ transition: `width ${spring('bouncy')}` })
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or use the `spring.transition()` helper for multiple properties:
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
css({ transition: spring.transition('width', 'bouncy') })
|
|
139
|
+
css({ transition: spring.transition(['left', 'top'], 'snappy') })
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Web Animations API
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
element.animate(keyframes, { ...spring('bouncy') })
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### JS iteration
|
|
149
|
+
|
|
150
|
+
The iterator yields position values from 0 to 1, one per frame:
|
|
151
|
+
|
|
152
|
+
```tsx
|
|
153
|
+
for (let t of spring('bouncy')) {
|
|
154
|
+
let x = from + (to - from) * t
|
|
155
|
+
updateSomething(x)
|
|
156
|
+
await nextFrame()
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Tween API
|
|
161
|
+
|
|
162
|
+
Generator-based tween for animating values over time with cubic bezier easing. Prefer animation
|
|
163
|
+
mixins or CSS transitions with `spring` for most UI work. Use `tween` for imperative
|
|
164
|
+
`requestAnimationFrame` loops, canvas/WebGL, or non-CSS properties.
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { tween, easings } from 'remix/ui/animation'
|
|
168
|
+
|
|
169
|
+
let animation = tween({
|
|
170
|
+
from: 0,
|
|
171
|
+
to: 100,
|
|
172
|
+
duration: 300,
|
|
173
|
+
curve: easings.easeOut,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
animation.next() // initialize
|
|
177
|
+
function tick(timestamp: number) {
|
|
178
|
+
if (handle.signal.aborted) return
|
|
179
|
+
let { value, done } = animation.next(timestamp)
|
|
180
|
+
element.style.transform = `translateX(${value}px)`
|
|
181
|
+
if (!done) requestAnimationFrame(tick)
|
|
182
|
+
}
|
|
183
|
+
requestAnimationFrame(tick)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Built-in easings: `easings.linear`, `easings.ease`, `easings.easeIn`, `easings.easeOut`,
|
|
187
|
+
`easings.easeInOut`.
|
|
188
|
+
|
|
189
|
+
## Practical Guidance
|
|
190
|
+
|
|
191
|
+
- Always key conditional or switching elements you expect to animate.
|
|
192
|
+
- Use `animateLayout` only on the element whose position or size changes.
|
|
193
|
+
- Prefer one clear transition intent per mixin: entrance starts from a style, exit ends at a style.
|
|
194
|
+
- Default to `...spring()` for duration and easing in most cases.
|
|
195
|
+
- Keep DOM work in `handle.queueTask(...)` or `ref(...)`, not in render.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Assets and Browser Modules
|
|
2
|
+
|
|
3
|
+
## What This Covers
|
|
4
|
+
|
|
5
|
+
How to serve browser scripts and styles from source. Read this when the task involves:
|
|
6
|
+
|
|
7
|
+
- Configuring `createAssetServer` (`fileMap`, `allow`, `deny`, fingerprinting, compiler options)
|
|
8
|
+
- Choosing between `staticFiles()` for already-built files and `createAssetServer()` for source
|
|
9
|
+
assets that need import rewriting, preloads, or fingerprinted URLs
|
|
10
|
+
- Generating script URLs or `<link rel="modulepreload">` tags for a client entry
|
|
11
|
+
- Keeping server-only files out of the browser via `deny` rules
|
|
12
|
+
|
|
13
|
+
For routing the URL namespace itself, see `routing-and-controllers.md`. For client entry
|
|
14
|
+
hydration, see `hydration-frames-navigation.md`.
|
|
15
|
+
|
|
16
|
+
## When To Reach For It
|
|
17
|
+
|
|
18
|
+
Use `remix/assets` when the app serves browser JavaScript, TypeScript, or CSS from source files.
|
|
19
|
+
This is the right tool for client entrypoints, browser-only helpers, styles under `app/assets/`,
|
|
20
|
+
and monorepo code that should be compiled and served under a public URL namespace.
|
|
21
|
+
|
|
22
|
+
Use `staticFiles()` for files that already exist on disk exactly as they should be served. Use
|
|
23
|
+
`createAssetServer()` for source scripts or styles that need rewriting, dependency scanning,
|
|
24
|
+
preloads, sourcemaps, or fingerprinted URLs.
|
|
25
|
+
|
|
26
|
+
## Default Pattern
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import * as path from 'node:path'
|
|
30
|
+
|
|
31
|
+
import { createAssetServer } from 'remix/assets'
|
|
32
|
+
import { createRouter } from 'remix/fetch-router'
|
|
33
|
+
|
|
34
|
+
let assetServer = createAssetServer({
|
|
35
|
+
rootDir: path.resolve(import.meta.dirname, '..'),
|
|
36
|
+
fileMap: {
|
|
37
|
+
'/assets/app/*path': 'app/*path',
|
|
38
|
+
'/assets/packages/*path': '../packages/*path',
|
|
39
|
+
},
|
|
40
|
+
allow: ['app/assets/**', '../packages/**'],
|
|
41
|
+
deny: ['app/**/*.server.*'],
|
|
42
|
+
target: { es: '2020', chrome: '109', safari: '16.4' },
|
|
43
|
+
sourceMaps: process.env.NODE_ENV === 'development' ? 'external' : undefined,
|
|
44
|
+
minify: process.env.NODE_ENV === 'production',
|
|
45
|
+
scripts: {
|
|
46
|
+
define: {
|
|
47
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'development'),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
let router = createRouter()
|
|
53
|
+
|
|
54
|
+
router.get('/assets/*path', ({ request }) => {
|
|
55
|
+
return assetServer.fetch(request)
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Rules
|
|
60
|
+
|
|
61
|
+
- Treat `allow` and `deny` as the security boundary for browser-reachable source files.
|
|
62
|
+
- Add a `deny` list for server-only modules such as `*.server.*`, private config, or other files
|
|
63
|
+
that should never be exposed.
|
|
64
|
+
- Set `rootDir` explicitly in monorepos so relative paths resolve from the intended project root.
|
|
65
|
+
- `fileMap` keys are public URL patterns and values are root-relative file path patterns. They use
|
|
66
|
+
`route-pattern` syntax on both sides.
|
|
67
|
+
- Keep the same wildcard params on both sides of a `fileMap` entry so import rewriting can map
|
|
68
|
+
source files back to public URLs.
|
|
69
|
+
- CSS files are compiled and served alongside scripts. Local CSS `@import` rules are rewritten and
|
|
70
|
+
fingerprinted with the same asset server routing rules.
|
|
71
|
+
|
|
72
|
+
## Rendering HTML
|
|
73
|
+
|
|
74
|
+
Use `getHref()` when you need the public URL for one module, and `getPreloads()` when you want
|
|
75
|
+
`<link rel="modulepreload">` tags or `Link` headers for one or more entrypoints and their
|
|
76
|
+
dependencies.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
let entryHref = await assetServer.getHref('app/assets/entry.ts')
|
|
80
|
+
let preloads = await assetServer.getPreloads(['app/assets/entry.ts'])
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Use this when rendering documents or layouts that boot browser behavior with a known client entry.
|
|
84
|
+
|
|
85
|
+
When resolving hydrated client entries during server rendering, pass the source entry ID from
|
|
86
|
+
`clientEntry(import.meta.url, ...)` to `getHref()` inside `resolveClientEntry`. Keep export-name
|
|
87
|
+
resolution in that render helper, and avoid hard-coding public asset URLs in source-owned component
|
|
88
|
+
modules.
|
|
89
|
+
|
|
90
|
+
## Development vs Deployment
|
|
91
|
+
|
|
92
|
+
In development:
|
|
93
|
+
|
|
94
|
+
- Keep `watch` enabled so source changes are picked up without restarting the server
|
|
95
|
+
- Prefer stable URLs with normal revalidation
|
|
96
|
+
- Enable source maps when debugging browser code
|
|
97
|
+
|
|
98
|
+
In deployment:
|
|
99
|
+
|
|
100
|
+
- Set `watch: false`
|
|
101
|
+
- Use `fingerprint: { buildId }` for long-lived immutable caching
|
|
102
|
+
- Make sure `buildId` changes for each deploy
|
|
103
|
+
|
|
104
|
+
Fingerprinting assumes files on disk are stable and requires `watch: false`.
|
|
105
|
+
|
|
106
|
+
## Useful Compiler Options
|
|
107
|
+
|
|
108
|
+
- `minify` for production minification of scripts and styles
|
|
109
|
+
- `sourceMaps` for `'external'` or `'inline'` source maps for scripts and styles
|
|
110
|
+
- `sourceMapSourcePaths` for `'url'` or `'absolute'` source map paths
|
|
111
|
+
- `target` as an object for shared browser targets and script-only ECMAScript output, such as
|
|
112
|
+
`{ es: '2020', chrome: '109', safari: '16.4' }`
|
|
113
|
+
- `scripts.define` to replace globals such as `process.env.NODE_ENV`
|
|
114
|
+
- `scripts.external` to leave specific script imports untouched
|
|
115
|
+
|
|
116
|
+
Do not nest shared compiler options under `scripts`. Use top-level `minify`, `sourceMaps`,
|
|
117
|
+
`sourceMapSourcePaths`, and `target` so they apply to styles as well as scripts.
|
|
118
|
+
|
|
119
|
+
## Lifecycle
|
|
120
|
+
|
|
121
|
+
If the asset server is long-lived and watching the file system, call `await assetServer.close()`
|
|
122
|
+
when shutting down dev servers or disposing tests.
|