@remix-run/cli 0.0.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/LICENSE +21 -0
- package/README.md +77 -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 +39 -0
- package/bootstrap/README.md +27 -0
- package/bootstrap/app/assets/entry.ts +19 -0
- package/bootstrap/app/assets.ts +18 -0
- package/bootstrap/app/controllers/auth.tsx +21 -0
- package/bootstrap/app/controllers/home.tsx +11 -0
- package/bootstrap/app/router.ts +16 -0
- package/bootstrap/app/routes.ts +7 -0
- package/bootstrap/app/ui/document.tsx +26 -0
- package/bootstrap/app/ui/layout.tsx +22 -0
- 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 +26 -0
- package/bootstrap/package.json +22 -0
- package/bootstrap/server.ts +37 -0
- package/bootstrap/tsconfig.json +18 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/dist/lib/bootstrap-project.d.ts +17 -0
- package/dist/lib/bootstrap-project.d.ts.map +1 -0
- package/dist/lib/bootstrap-project.js +137 -0
- package/dist/lib/cli-context.d.ts +11 -0
- package/dist/lib/cli-context.d.ts.map +1 -0
- package/dist/lib/cli-context.js +19 -0
- package/dist/lib/cli.d.ts +6 -0
- package/dist/lib/cli.d.ts.map +1 -0
- package/dist/lib/cli.js +84 -0
- package/dist/lib/commands/completion.d.ts +3 -0
- package/dist/lib/commands/completion.d.ts.map +1 -0
- package/dist/lib/commands/completion.js +51 -0
- package/dist/lib/commands/doctor.d.ts +4 -0
- package/dist/lib/commands/doctor.d.ts.map +1 -0
- package/dist/lib/commands/doctor.js +293 -0
- package/dist/lib/commands/help.d.ts +4 -0
- package/dist/lib/commands/help.d.ts.map +1 -0
- package/dist/lib/commands/help.js +100 -0
- package/dist/lib/commands/new.d.ts +4 -0
- package/dist/lib/commands/new.d.ts.map +1 -0
- package/dist/lib/commands/new.js +70 -0
- package/dist/lib/commands/routes.d.ts +4 -0
- package/dist/lib/commands/routes.d.ts.map +1 -0
- package/dist/lib/commands/routes.js +161 -0
- package/dist/lib/commands/test.d.ts +4 -0
- package/dist/lib/commands/test.d.ts.map +1 -0
- package/dist/lib/commands/test.js +23 -0
- package/dist/lib/commands/version.d.ts +4 -0
- package/dist/lib/commands/version.d.ts.map +1 -0
- package/dist/lib/commands/version.js +29 -0
- package/dist/lib/completion.d.ts +12 -0
- package/dist/lib/completion.d.ts.map +1 -0
- package/dist/lib/completion.js +310 -0
- package/dist/lib/contained-path.d.ts +2 -0
- package/dist/lib/contained-path.d.ts.map +1 -0
- package/dist/lib/contained-path.js +10 -0
- package/dist/lib/controller-files.d.ts +14 -0
- package/dist/lib/controller-files.d.ts.map +1 -0
- package/dist/lib/controller-files.js +53 -0
- package/dist/lib/controller-ownership.d.ts +41 -0
- package/dist/lib/controller-ownership.d.ts.map +1 -0
- package/dist/lib/controller-ownership.js +224 -0
- package/dist/lib/display-path.d.ts +2 -0
- package/dist/lib/display-path.d.ts.map +1 -0
- package/dist/lib/display-path.js +12 -0
- package/dist/lib/doctor/controller-findings.d.ts +4 -0
- package/dist/lib/doctor/controller-findings.d.ts.map +1 -0
- package/dist/lib/doctor/controller-findings.js +132 -0
- package/dist/lib/doctor/controller-fix-plans.d.ts +4 -0
- package/dist/lib/doctor/controller-fix-plans.d.ts.map +1 -0
- package/dist/lib/doctor/controller-fix-plans.js +130 -0
- package/dist/lib/doctor/controller-placeholders.d.ts +4 -0
- package/dist/lib/doctor/controller-placeholders.d.ts.map +1 -0
- package/dist/lib/doctor/controller-placeholders.js +183 -0
- package/dist/lib/doctor/controllers.d.ts +8 -0
- package/dist/lib/doctor/controllers.d.ts.map +1 -0
- package/dist/lib/doctor/controllers.js +13 -0
- package/dist/lib/doctor/environment.d.ts +17 -0
- package/dist/lib/doctor/environment.d.ts.map +1 -0
- package/dist/lib/doctor/environment.js +226 -0
- package/dist/lib/doctor/fixes.d.ts +3 -0
- package/dist/lib/doctor/fixes.d.ts.map +1 -0
- package/dist/lib/doctor/fixes.js +65 -0
- package/dist/lib/doctor/project.d.ts +10 -0
- package/dist/lib/doctor/project.d.ts.map +1 -0
- package/dist/lib/doctor/project.js +371 -0
- package/dist/lib/doctor/types.d.ts +48 -0
- package/dist/lib/doctor/types.d.ts.map +1 -0
- package/dist/lib/doctor/types.js +15 -0
- package/dist/lib/errors.d.ts +167 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +307 -0
- package/dist/lib/help-text.d.ts +13 -0
- package/dist/lib/help-text.d.ts.map +1 -0
- package/dist/lib/help-text.js +43 -0
- package/dist/lib/load-route-map-worker.d.ts +2 -0
- package/dist/lib/load-route-map-worker.d.ts.map +1 -0
- package/dist/lib/load-route-map-worker.js +92 -0
- package/dist/lib/parse-args.d.ts +22 -0
- package/dist/lib/parse-args.d.ts.map +1 -0
- package/dist/lib/parse-args.js +35 -0
- package/dist/lib/remix-version.d.ts +2 -0
- package/dist/lib/remix-version.d.ts.map +1 -0
- package/dist/lib/remix-version.js +58 -0
- package/dist/lib/reporter.d.ts +56 -0
- package/dist/lib/reporter.d.ts.map +1 -0
- package/dist/lib/reporter.js +357 -0
- package/dist/lib/route-map.d.ts +38 -0
- package/dist/lib/route-map.d.ts.map +1 -0
- package/dist/lib/route-map.js +195 -0
- package/dist/lib/terminal.d.ts +17 -0
- package/dist/lib/terminal.d.ts.map +1 -0
- package/dist/lib/terminal.js +66 -0
- package/package.json +47 -5
- package/src/index.ts +1 -0
- package/src/lib/bootstrap-project.ts +222 -0
- package/src/lib/cli-context.ts +38 -0
- package/src/lib/cli.ts +116 -0
- package/src/lib/commands/completion.ts +74 -0
- package/src/lib/commands/doctor.ts +393 -0
- package/src/lib/commands/help.ts +123 -0
- package/src/lib/commands/new.ts +104 -0
- package/src/lib/commands/routes.ts +251 -0
- package/src/lib/commands/test.ts +31 -0
- package/src/lib/commands/version.ts +39 -0
- package/src/lib/completion.ts +418 -0
- package/src/lib/contained-path.ts +13 -0
- package/src/lib/controller-files.ts +79 -0
- package/src/lib/controller-ownership.ts +397 -0
- package/src/lib/display-path.ts +16 -0
- package/src/lib/doctor/controller-findings.ts +157 -0
- package/src/lib/doctor/controller-fix-plans.ts +184 -0
- package/src/lib/doctor/controller-placeholders.ts +242 -0
- package/src/lib/doctor/controllers.ts +23 -0
- package/src/lib/doctor/environment.ts +289 -0
- package/src/lib/doctor/fixes.ts +84 -0
- package/src/lib/doctor/project.ts +435 -0
- package/src/lib/doctor/types.ts +95 -0
- package/src/lib/errors.ts +367 -0
- package/src/lib/help-text.ts +88 -0
- package/src/lib/load-route-map-worker.ts +110 -0
- package/src/lib/parse-args.ts +82 -0
- package/src/lib/remix-version.ts +80 -0
- package/src/lib/reporter.ts +535 -0
- package/src/lib/route-map.ts +303 -0
- package/src/lib/terminal.ts +86 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# %%RMX_APP_DISPLAY_NAME%% Agent Guide
|
|
2
|
+
|
|
3
|
+
This app was scaffolded with `remix new`. Use these conventions when continuing to build it out.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm i
|
|
9
|
+
npm run start
|
|
10
|
+
npm test
|
|
11
|
+
npm run typecheck
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Building Features
|
|
15
|
+
|
|
16
|
+
Refer to ./agents/skills/remix/SKILL.md
|
|
17
|
+
|
|
18
|
+
## Starter Layout
|
|
19
|
+
|
|
20
|
+
- `app/controllers/home.tsx` owns the home page
|
|
21
|
+
- `app/controllers/auth.tsx` owns the auth page
|
|
22
|
+
- `app/routes.ts` defines the route contract
|
|
23
|
+
- `app/router.ts` wires routes to route handlers
|
|
24
|
+
- `app/ui/` holds the shared document and layout wrappers
|
|
25
|
+
- `app/utils/render.tsx` centralizes HTML response rendering
|
|
26
|
+
|
|
27
|
+
## Route Ownership
|
|
28
|
+
|
|
29
|
+
- Start from `app/routes.ts` and map each route to the narrowest owner on disk.
|
|
30
|
+
- Keep simple pages in flat files like `app/controllers/home.tsx` and `app/controllers/auth.tsx`.
|
|
31
|
+
- Promote a route into a controller folder with `controller.tsx` only when it gains nested routes, multiple actions, or route-owned modules.
|
|
32
|
+
- Keep route-owned page modules next to the route that owns them.
|
|
33
|
+
- Move shared UI to `app/ui/`, not `app/controllers/`.
|
|
34
|
+
|
|
35
|
+
## Build-Out Notes
|
|
36
|
+
|
|
37
|
+
- This starter intentionally begins small; add directories like `app/data/`, `app/middleware/`, `public/`, and `test/` only when you need them.
|
|
38
|
+
- Prefer putting code in the narrowest owner before introducing shared modules.
|
|
39
|
+
- Avoid generic dumping-ground directories like `app/lib/` or `app/components/`.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# %%RMX_APP_DISPLAY_NAME%%
|
|
2
|
+
|
|
3
|
+
A minimal Remix application starter with a home page and an auth page.
|
|
4
|
+
|
|
5
|
+
## Starter Shape
|
|
6
|
+
|
|
7
|
+
- `app/controllers/home.tsx` owns the home page.
|
|
8
|
+
- `app/controllers/auth.tsx` owns the auth page.
|
|
9
|
+
- `app/routes.ts` defines the route contract.
|
|
10
|
+
- `app/router.ts` wires routes to handlers.
|
|
11
|
+
- `app/ui/` holds the shared document and layout wrappers.
|
|
12
|
+
- `app/utils/render.tsx` centralizes HTML response rendering.
|
|
13
|
+
|
|
14
|
+
## Growing The App
|
|
15
|
+
|
|
16
|
+
- Start with flat route files and only introduce route folders when a route needs multiple actions or route-owned modules.
|
|
17
|
+
- Add directories like `app/data/`, `app/middleware/`, `public/`, or `test/` when the app actually needs them.
|
|
18
|
+
- Move shared UI into `app/ui/` once more than one route needs it.
|
|
19
|
+
|
|
20
|
+
## Commands
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npm i
|
|
24
|
+
npm run start
|
|
25
|
+
npm test
|
|
26
|
+
npm run typecheck
|
|
27
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { run } from 'remix/ui'
|
|
2
|
+
|
|
3
|
+
run({
|
|
4
|
+
async loadModule(moduleUrl, exportName) {
|
|
5
|
+
let mod = await import(moduleUrl)
|
|
6
|
+
return mod[exportName]
|
|
7
|
+
},
|
|
8
|
+
async resolveFrame(src, signal, target) {
|
|
9
|
+
let headers = new Headers({ accept: 'text/html' })
|
|
10
|
+
if (target) headers.set('x-remix-target', target)
|
|
11
|
+
|
|
12
|
+
let response = await fetch(src, {
|
|
13
|
+
credentials: 'same-origin',
|
|
14
|
+
headers,
|
|
15
|
+
signal,
|
|
16
|
+
})
|
|
17
|
+
return response.body ?? response.text()
|
|
18
|
+
},
|
|
19
|
+
})
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createAssetServer } from 'remix/assets'
|
|
2
|
+
|
|
3
|
+
export const assets = createAssetServer({
|
|
4
|
+
basePath: '/assets',
|
|
5
|
+
rootDir: process.cwd(),
|
|
6
|
+
fileMap: {
|
|
7
|
+
'app/*path': 'app/*path',
|
|
8
|
+
'node_modules/*path': 'node_modules/*path',
|
|
9
|
+
},
|
|
10
|
+
allow: ['app/assets/**', 'app/ui/prompt-button.tsx', 'node_modules/**'],
|
|
11
|
+
deny: ['app/**/*.server.*'],
|
|
12
|
+
sourceMaps: process.env.NODE_ENV === 'development' ? 'external' : undefined,
|
|
13
|
+
scripts: {
|
|
14
|
+
define: {
|
|
15
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV ?? 'development'),
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BuildAction } from 'remix/fetch-router'
|
|
2
|
+
|
|
3
|
+
import type { routes } from '../routes.ts'
|
|
4
|
+
import { Layout } from '../ui/layout.tsx'
|
|
5
|
+
import { render } from '../utils/render.tsx'
|
|
6
|
+
|
|
7
|
+
export const auth: BuildAction<'GET', typeof routes.auth> = {
|
|
8
|
+
handler({ request }) {
|
|
9
|
+
return render(<AuthPage />, request)
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function AuthPage() {
|
|
14
|
+
return () => (
|
|
15
|
+
<Layout title="Auth">
|
|
16
|
+
<h1>Auth</h1>
|
|
17
|
+
<p>Use this route to start building sign-in, sign-up, and session flows.</p>
|
|
18
|
+
<p>Keep it as a flat file until the route needs multiple actions or route-owned modules.</p>
|
|
19
|
+
</Layout>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BuildAction } from 'remix/fetch-router'
|
|
2
|
+
|
|
3
|
+
import type { routes } from '../routes.ts'
|
|
4
|
+
import { HomePage } from '../ui/scaffold-home-page.tsx'
|
|
5
|
+
import { render } from '../utils/render.tsx'
|
|
6
|
+
|
|
7
|
+
export const home: BuildAction<'GET', typeof routes.home> = {
|
|
8
|
+
handler({ request }) {
|
|
9
|
+
return render(<HomePage />, request)
|
|
10
|
+
},
|
|
11
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createRouter } from 'remix/fetch-router'
|
|
2
|
+
|
|
3
|
+
import { assets } from './assets.ts'
|
|
4
|
+
import { auth } from './controllers/auth.tsx'
|
|
5
|
+
import { home } from './controllers/home.tsx'
|
|
6
|
+
import { routes } from './routes.ts'
|
|
7
|
+
|
|
8
|
+
export const router = createRouter()
|
|
9
|
+
|
|
10
|
+
router.get(routes.assets, async ({ request }) => {
|
|
11
|
+
let response = await assets.fetch(request)
|
|
12
|
+
return response ?? new Response('Not Found', { status: 404 })
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
router.map(routes.home, home)
|
|
16
|
+
router.map(routes.auth, auth)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { RemixNode } from 'remix/ui'
|
|
2
|
+
|
|
3
|
+
import { routes } from '../routes.ts'
|
|
4
|
+
|
|
5
|
+
export interface DocumentProps {
|
|
6
|
+
children?: RemixNode
|
|
7
|
+
title?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const DEFAULT_TITLE = decodeURIComponent('%%RMX_APP_DISPLAY_NAME_URI_COMPONENT%%')
|
|
11
|
+
|
|
12
|
+
export function Document() {
|
|
13
|
+
return ({ title = DEFAULT_TITLE, children }: DocumentProps) => (
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charSet="utf-8" />
|
|
17
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
18
|
+
<title>{title}</title>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
{children}
|
|
22
|
+
<script type="module" src={routes.assets.href({ path: 'app/assets/entry.ts' })}></script>
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RemixNode } from 'remix/ui'
|
|
2
|
+
|
|
3
|
+
import { routes } from '../routes.ts'
|
|
4
|
+
import { Document } from './document.tsx'
|
|
5
|
+
|
|
6
|
+
export interface LayoutProps {
|
|
7
|
+
children?: RemixNode
|
|
8
|
+
title?: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function Layout() {
|
|
12
|
+
return ({ title, children }: LayoutProps) => (
|
|
13
|
+
<Document title={title}>
|
|
14
|
+
<header>
|
|
15
|
+
<nav>
|
|
16
|
+
<a href={routes.home.href()}>Home</a> <a href={routes.auth.href()}>Auth</a>
|
|
17
|
+
</nav>
|
|
18
|
+
</header>
|
|
19
|
+
<main>{children}</main>
|
|
20
|
+
</Document>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { clientEntry, css, on, type Handle, type SerializableProps } from 'remix/ui'
|
|
2
|
+
|
|
3
|
+
const FADE_MS = 180
|
|
4
|
+
const HOLD_MS = 1200
|
|
5
|
+
|
|
6
|
+
type CopyState = 'idle' | 'copied' | 'failed' | 'resetting'
|
|
7
|
+
|
|
8
|
+
interface PromptButtonProps extends SerializableProps {
|
|
9
|
+
text: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const PromptButton = clientEntry(
|
|
13
|
+
'/assets/app/ui/prompt-button.tsx#PromptButton',
|
|
14
|
+
function PromptButton(handle: Handle<PromptButtonProps>) {
|
|
15
|
+
let state: CopyState = 'idle'
|
|
16
|
+
|
|
17
|
+
return () => {
|
|
18
|
+
let promptLabel = `\u201C${handle.props.text}\u201D`
|
|
19
|
+
let label =
|
|
20
|
+
state === 'copied' || state === 'resetting'
|
|
21
|
+
? 'Copied to clipboard'
|
|
22
|
+
: state === 'failed'
|
|
23
|
+
? 'Copy failed'
|
|
24
|
+
: promptLabel
|
|
25
|
+
let active = state === 'copied' || state === 'failed' || state === 'resetting'
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<button
|
|
29
|
+
type="button"
|
|
30
|
+
className={state}
|
|
31
|
+
style={{
|
|
32
|
+
background: active ? 'var(--surface-4)' : undefined,
|
|
33
|
+
color: active ? 'var(--brand-blue)' : undefined,
|
|
34
|
+
}}
|
|
35
|
+
mix={[
|
|
36
|
+
buttonStyle,
|
|
37
|
+
on('click', async (_event, signal) => {
|
|
38
|
+
try {
|
|
39
|
+
await navigator.clipboard.writeText(handle.props.text)
|
|
40
|
+
if (signal.aborted) return
|
|
41
|
+
} catch {
|
|
42
|
+
state = 'failed'
|
|
43
|
+
await handle.update()
|
|
44
|
+
await wait(HOLD_MS)
|
|
45
|
+
if (signal.aborted) return
|
|
46
|
+
state = 'resetting'
|
|
47
|
+
await handle.update()
|
|
48
|
+
await wait(FADE_MS)
|
|
49
|
+
if (signal.aborted) return
|
|
50
|
+
state = 'idle'
|
|
51
|
+
handle.update()
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
state = 'copied'
|
|
56
|
+
await handle.update()
|
|
57
|
+
await wait(HOLD_MS)
|
|
58
|
+
if (signal.aborted) return
|
|
59
|
+
|
|
60
|
+
state = 'resetting'
|
|
61
|
+
await handle.update()
|
|
62
|
+
await wait(FADE_MS)
|
|
63
|
+
if (signal.aborted) return
|
|
64
|
+
|
|
65
|
+
state = 'idle'
|
|
66
|
+
await handle.update()
|
|
67
|
+
}),
|
|
68
|
+
]}
|
|
69
|
+
>
|
|
70
|
+
<span aria-hidden="true" mix={iconSlotStyle}>
|
|
71
|
+
<CopyIcon />
|
|
72
|
+
</span>
|
|
73
|
+
<span
|
|
74
|
+
mix={css({
|
|
75
|
+
alignItems: 'center',
|
|
76
|
+
display: 'flex',
|
|
77
|
+
fontSize: '14px',
|
|
78
|
+
flex: '1 1 0',
|
|
79
|
+
lineHeight: 1.5,
|
|
80
|
+
minWidth: 0,
|
|
81
|
+
position: 'relative',
|
|
82
|
+
transition: 'opacity 180ms ease',
|
|
83
|
+
})}
|
|
84
|
+
style={{ opacity: state === 'resetting' ? 0 : undefined }}
|
|
85
|
+
>
|
|
86
|
+
<span
|
|
87
|
+
aria-hidden={state === 'idle' ? true : undefined}
|
|
88
|
+
style={{
|
|
89
|
+
alignItems: 'center',
|
|
90
|
+
display: 'flex',
|
|
91
|
+
inset: 0,
|
|
92
|
+
position: 'absolute',
|
|
93
|
+
visibility: state === 'idle' ? 'hidden' : 'visible',
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
{label}
|
|
97
|
+
</span>
|
|
98
|
+
<span
|
|
99
|
+
aria-hidden={state === 'idle' ? undefined : true}
|
|
100
|
+
style={{ visibility: state === 'idle' ? 'visible' : 'hidden' }}
|
|
101
|
+
>
|
|
102
|
+
{promptLabel}
|
|
103
|
+
</span>
|
|
104
|
+
</span>
|
|
105
|
+
</button>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
export function CopyIcon() {
|
|
112
|
+
return () => (
|
|
113
|
+
<svg viewBox="0 0 14 16.5" fill="none">
|
|
114
|
+
<path
|
|
115
|
+
d="M0.75 9.188L0.75 4.083C0.75 2.242 2.242 0.75 4.083 0.75L9.188 0.75M5.75 15.75L11.375 15.75C12.41 15.75 13.25 14.91 13.25 13.875L13.25 5.75C13.25 4.714 12.41 3.875 11.375 3.875L5.75 3.875C4.714 3.875 3.875 4.714 3.875 5.75L3.875 13.875C3.875 14.91 4.714 15.75 5.75 15.75Z"
|
|
116
|
+
stroke="currentColor"
|
|
117
|
+
stroke-width="1.5"
|
|
118
|
+
stroke-linecap="round"
|
|
119
|
+
/>
|
|
120
|
+
</svg>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function wait(ms: number) {
|
|
125
|
+
return new Promise<void>((resolve) => setTimeout(resolve, ms))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const buttonStyle = css({
|
|
129
|
+
appearance: 'none',
|
|
130
|
+
font: 'inherit',
|
|
131
|
+
textAlign: 'left',
|
|
132
|
+
cursor: 'pointer',
|
|
133
|
+
width: '100%',
|
|
134
|
+
display: 'flex',
|
|
135
|
+
gap: '16px',
|
|
136
|
+
alignItems: 'center',
|
|
137
|
+
padding: '16px',
|
|
138
|
+
border: 0,
|
|
139
|
+
borderRadius: '12px',
|
|
140
|
+
color: 'var(--text-primary)',
|
|
141
|
+
background: 'transparent',
|
|
142
|
+
transition: 'background-color 150ms ease, color 150ms ease',
|
|
143
|
+
'&:hover, &:focus-visible': {
|
|
144
|
+
background: 'var(--surface-4)',
|
|
145
|
+
color: 'var(--brand-blue)',
|
|
146
|
+
outline: 'none',
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
const iconSlotStyle = css({
|
|
151
|
+
flex: '0 0 24px',
|
|
152
|
+
width: '24px',
|
|
153
|
+
display: 'flex',
|
|
154
|
+
alignItems: 'center',
|
|
155
|
+
justifyContent: 'center',
|
|
156
|
+
'& svg': {
|
|
157
|
+
width: '20px',
|
|
158
|
+
height: '20px',
|
|
159
|
+
display: 'block',
|
|
160
|
+
transform: 'rotate(180deg)',
|
|
161
|
+
},
|
|
162
|
+
})
|