@nrwl/remix 1.0.0-alpha.1
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 +7 -0
- package/generators.json +13 -0
- package/package.json +12 -0
- package/src/generators/application/application.impl.d.ts +3 -0
- package/src/generators/application/application.impl.js +45 -0
- package/src/generators/application/application.impl.js.map +1 -0
- package/src/generators/application/lib/normalize-options.d.ts +8 -0
- package/src/generators/application/lib/normalize-options.js +17 -0
- package/src/generators/application/lib/normalize-options.js.map +1 -0
- package/src/generators/application/schema.d.ts +5 -0
- package/src/generators/application/schema.json +28 -0
- package/src/generators/preset/files/README.md +53 -0
- package/src/generators/preset/files/app/entry.client.tsx__tmpl__ +4 -0
- package/src/generators/preset/files/app/entry.server.tsx__tmpl__ +21 -0
- package/src/generators/preset/files/app/root.tsx__tmpl__ +178 -0
- package/src/generators/preset/files/app/routes/demos/about/index.tsx__tmpl__ +17 -0
- package/src/generators/preset/files/app/routes/demos/about/whoa.tsx__tmpl__ +20 -0
- package/src/generators/preset/files/app/routes/demos/about.tsx__tmpl__ +44 -0
- package/src/generators/preset/files/app/routes/demos/actions.tsx__tmpl__ +101 -0
- package/src/generators/preset/files/app/routes/demos/correct.tsx__tmpl__ +3 -0
- package/src/generators/preset/files/app/routes/demos/params/$id.tsx__tmpl__ +110 -0
- package/src/generators/preset/files/app/routes/demos/params/index.tsx__tmpl__ +40 -0
- package/src/generators/preset/files/app/routes/demos/params.tsx__tmpl__ +43 -0
- package/src/generators/preset/files/app/routes/index.tsx__tmpl__ +100 -0
- package/src/generators/preset/files/app/styles/dark.css +7 -0
- package/src/generators/preset/files/app/styles/demos/about.css +26 -0
- package/src/generators/preset/files/app/styles/global.css +216 -0
- package/src/generators/preset/files/package.json__tmpl__ +29 -0
- package/src/generators/preset/files/public/favicon.ico +0 -0
- package/src/generators/preset/files/remix.config.js__tmpl__ +10 -0
- package/src/generators/preset/files/remix.env.d.ts__tmpl__ +2 -0
- package/src/generators/preset/files/tsconfig.json__tmpl__ +16 -0
- package/src/generators/preset/lib/normalize-options.d.ts +8 -0
- package/src/generators/preset/lib/normalize-options.js +17 -0
- package/src/generators/preset/lib/normalize-options.js.map +1 -0
- package/src/generators/preset/preset.impl.d.ts +3 -0
- package/src/generators/preset/preset.impl.js +28 -0
- package/src/generators/preset/preset.impl.js.map +1 -0
- package/src/generators/preset/schema.d.ts +4 -0
- package/src/generators/preset/schema.json +23 -0
- package/src/index.d.ts +0 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useCatch, Link, json, useLoaderData } from "remix";
|
|
2
|
+
import type { LoaderFunction, MetaFunction } from "remix";
|
|
3
|
+
|
|
4
|
+
// The `$` in route filenames becomes a pattern that's parsed from the URL and
|
|
5
|
+
// passed to your loaders so you can look up data.
|
|
6
|
+
// - https://remix.run/api/conventions#loader-params
|
|
7
|
+
export let loader: LoaderFunction = async ({ params }) => {
|
|
8
|
+
// pretend like we're using params.id to look something up in the db
|
|
9
|
+
|
|
10
|
+
if (params.id === "this-record-does-not-exist") {
|
|
11
|
+
// If the record doesn't exist we can't render the route normally, so
|
|
12
|
+
// instead we throw a 404 reponse to stop running code here and show the
|
|
13
|
+
// user the catch boundary.
|
|
14
|
+
throw new Response("Not Found", { status: 404 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// now pretend like the record exists but the user just isn't authorized to
|
|
18
|
+
// see it.
|
|
19
|
+
if (params.id === "shh-its-a-secret") {
|
|
20
|
+
// Again, we can't render the component if the user isn't authorized. You
|
|
21
|
+
// can even put data in the response that might help the user rectify the
|
|
22
|
+
// issue! Like emailing the webmaster for access to the page. (Oh, right,
|
|
23
|
+
// `json` is just a Response helper that makes it easier to send JSON
|
|
24
|
+
// responses).
|
|
25
|
+
throw json({ webmasterEmail: "hello@remix.run" }, { status: 401 });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Sometimes your code just blows up and you never anticipated it. Remix will
|
|
29
|
+
// automatically catch it and send the UI to the error boundary.
|
|
30
|
+
if (params.id === "kaboom") {
|
|
31
|
+
lol();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// but otherwise the record was found, user has access, so we can do whatever
|
|
35
|
+
// else we needed to in the loader and return the data. (This is boring, we're
|
|
36
|
+
// just gonna return the params.id).
|
|
37
|
+
return { param: params.id };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default function ParamDemo() {
|
|
41
|
+
let data = useLoaderData();
|
|
42
|
+
return (
|
|
43
|
+
<h1>
|
|
44
|
+
The param is <i style={{ color: "red" }}>{data.param}</i>
|
|
45
|
+
</h1>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// https://remix.run/api/conventions#catchboundary
|
|
50
|
+
// https://remix.run/api/remix#usecatch
|
|
51
|
+
// https://remix.run/api/guides/not-found
|
|
52
|
+
export function CatchBoundary() {
|
|
53
|
+
let caught = useCatch();
|
|
54
|
+
|
|
55
|
+
let message: React.ReactNode;
|
|
56
|
+
switch (caught.status) {
|
|
57
|
+
case 401:
|
|
58
|
+
message = (
|
|
59
|
+
<p>
|
|
60
|
+
Looks like you tried to visit a page that you do not have access to.
|
|
61
|
+
Maybe ask the webmaster ({caught.data.webmasterEmail}) for access.
|
|
62
|
+
</p>
|
|
63
|
+
);
|
|
64
|
+
case 404:
|
|
65
|
+
message = (
|
|
66
|
+
<p>Looks like you tried to visit a page that does not exist.</p>
|
|
67
|
+
);
|
|
68
|
+
default:
|
|
69
|
+
message = (
|
|
70
|
+
<p>
|
|
71
|
+
There was a problem with your request!
|
|
72
|
+
<br />
|
|
73
|
+
{caught.status} {caught.statusText}
|
|
74
|
+
</p>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<>
|
|
80
|
+
<h2>Oops!</h2>
|
|
81
|
+
<p>{message}</p>
|
|
82
|
+
<p>
|
|
83
|
+
(Isn't it cool that the user gets to stay in context and try a different
|
|
84
|
+
link in the parts of the UI that didn't blow up?)
|
|
85
|
+
</p>
|
|
86
|
+
</>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// https://remix.run/api/conventions#errorboundary
|
|
91
|
+
// https://remix.run/api/guides/not-found
|
|
92
|
+
export function ErrorBoundary({ error }: { error: Error }) {
|
|
93
|
+
console.error(error);
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
<h2>Error!</h2>
|
|
97
|
+
<p>{error.message}</p>
|
|
98
|
+
<p>
|
|
99
|
+
(Isn't it cool that the user gets to stay in context and try a different
|
|
100
|
+
link in the parts of the UI that didn't blow up?)
|
|
101
|
+
</p>
|
|
102
|
+
</>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export let meta: MetaFunction = ({ data }) => {
|
|
107
|
+
return {
|
|
108
|
+
title: data ? `Param: ${data.param}` : "Oops...",
|
|
109
|
+
};
|
|
110
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useCatch, Link, json, useLoaderData, Outlet } from "remix";
|
|
2
|
+
import type { LoaderFunction } from "remix";
|
|
3
|
+
|
|
4
|
+
export default function Boundaries() {
|
|
5
|
+
return (
|
|
6
|
+
<>
|
|
7
|
+
<h2>Params</h2>
|
|
8
|
+
<p>
|
|
9
|
+
When you name a route segment with $ like{" "}
|
|
10
|
+
<code>routes/users/$userId.js</code>, the $ segment will be parsed from
|
|
11
|
+
the URL and sent to your loaders and actions by the same name.
|
|
12
|
+
</p>
|
|
13
|
+
<h2>Errors</h2>
|
|
14
|
+
<p>
|
|
15
|
+
When a route throws and error in it's action, loader, or component,
|
|
16
|
+
Remix automatically catches it, won't even try to render the component,
|
|
17
|
+
but it will render the route's ErrorBoundary instead. If the route
|
|
18
|
+
doesn't have one, it will bubble up to the routes above it until it hits
|
|
19
|
+
the root.
|
|
20
|
+
</p>
|
|
21
|
+
<p>So be as granular as you want with your error handling.</p>
|
|
22
|
+
<h2>Not Found</h2>
|
|
23
|
+
<p>
|
|
24
|
+
(and other{" "}
|
|
25
|
+
<a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses">
|
|
26
|
+
client errors
|
|
27
|
+
</a>
|
|
28
|
+
)
|
|
29
|
+
</p>
|
|
30
|
+
<p>
|
|
31
|
+
Loaders and Actions can throw a <code>Response</code> instead of an
|
|
32
|
+
error and Remix will render the CatchBoundary instead of the component.
|
|
33
|
+
This is great when loading data from a database isn't found. As soon as
|
|
34
|
+
you know you can't render the component normally, throw a 404 response
|
|
35
|
+
and send your app into the catch boundary. Just like error boundaries,
|
|
36
|
+
catch boundaries bubble, too.
|
|
37
|
+
</p>
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useCatch, Link, json, useLoaderData, Outlet } from "remix";
|
|
2
|
+
|
|
3
|
+
export function meta() {
|
|
4
|
+
return { title: "Boundaries Demo" };
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default function Boundaries() {
|
|
8
|
+
return (
|
|
9
|
+
<div className="remix__page">
|
|
10
|
+
<main>
|
|
11
|
+
<Outlet />
|
|
12
|
+
</main>
|
|
13
|
+
|
|
14
|
+
<aside>
|
|
15
|
+
<h2>Click these Links</h2>
|
|
16
|
+
<ul>
|
|
17
|
+
<li>
|
|
18
|
+
<Link to=".">Start over</Link>
|
|
19
|
+
</li>
|
|
20
|
+
<li>
|
|
21
|
+
<Link to="one">
|
|
22
|
+
Param: <i>one</i>
|
|
23
|
+
</Link>
|
|
24
|
+
</li>
|
|
25
|
+
<li>
|
|
26
|
+
<Link to="two">
|
|
27
|
+
Param: <i>two</i>
|
|
28
|
+
</Link>
|
|
29
|
+
</li>
|
|
30
|
+
<li>
|
|
31
|
+
<Link to="this-record-does-not-exist">This will be a 404</Link>
|
|
32
|
+
</li>
|
|
33
|
+
<li>
|
|
34
|
+
<Link to="shh-its-a-secret">And this will be 401 Unauthorized</Link>
|
|
35
|
+
</li>
|
|
36
|
+
<li>
|
|
37
|
+
<Link to="kaboom">This one will throw an error</Link>
|
|
38
|
+
</li>
|
|
39
|
+
</ul>
|
|
40
|
+
</aside>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { MetaFunction, LoaderFunction } from "remix";
|
|
2
|
+
import { useLoaderData, json, Link } from "remix";
|
|
3
|
+
|
|
4
|
+
type IndexData = {
|
|
5
|
+
resources: Array<{ name: string; url: string }>;
|
|
6
|
+
demos: Array<{ name: string; to: string }>;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// Loaders provide data to components and are only ever called on the server, so
|
|
10
|
+
// you can connect to a database or run any server side code you want right next
|
|
11
|
+
// to the component that renders it.
|
|
12
|
+
// https://remix.run/api/conventions#loader
|
|
13
|
+
export let loader: LoaderFunction = () => {
|
|
14
|
+
let data: IndexData = {
|
|
15
|
+
resources: [
|
|
16
|
+
{
|
|
17
|
+
name: "Remix Docs",
|
|
18
|
+
url: "https://remix.run/docs"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "React Router Docs",
|
|
22
|
+
url: "https://reactrouter.com/docs"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "Remix Discord",
|
|
26
|
+
url: "https://discord.gg/VBePs6d"
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
demos: [
|
|
30
|
+
{
|
|
31
|
+
to: "demos/actions",
|
|
32
|
+
name: "Actions"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
to: "demos/about",
|
|
36
|
+
name: "Nested Routes, CSS loading/unloading"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
to: "demos/params",
|
|
40
|
+
name: "URL Params and Error Boundaries"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// https://remix.run/api/remix#json
|
|
46
|
+
return json(data);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// https://remix.run/api/conventions#meta
|
|
50
|
+
export let meta: MetaFunction = () => {
|
|
51
|
+
return {
|
|
52
|
+
title: "Remix Starter",
|
|
53
|
+
description: "Welcome to remix!"
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// https://remix.run/guides/routing#index-routes
|
|
58
|
+
export default function Index() {
|
|
59
|
+
let data = useLoaderData<IndexData>();
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="remix__page">
|
|
63
|
+
<main>
|
|
64
|
+
<h2>Welcome to Remix!</h2>
|
|
65
|
+
<p>We're stoked that you're here. 🥳</p>
|
|
66
|
+
<p>
|
|
67
|
+
Feel free to take a look around the code to see how Remix does things,
|
|
68
|
+
it might be a bit different than what you’re used to. When you're
|
|
69
|
+
ready to dive deeper, we've got plenty of resources to get you
|
|
70
|
+
up-and-running quickly.
|
|
71
|
+
</p>
|
|
72
|
+
<p>
|
|
73
|
+
Check out all the demos in this starter, and then just delete the{" "}
|
|
74
|
+
<code>app/routes/demos</code> and <code>app/styles/demos</code>{" "}
|
|
75
|
+
folders when you're ready to turn this into your next project.
|
|
76
|
+
</p>
|
|
77
|
+
</main>
|
|
78
|
+
<aside>
|
|
79
|
+
<h2>Demos In This App</h2>
|
|
80
|
+
<ul>
|
|
81
|
+
{data.demos.map(demo => (
|
|
82
|
+
<li key={demo.to} className="remix__page__resource">
|
|
83
|
+
<Link to={demo.to} prefetch="intent">
|
|
84
|
+
{demo.name}
|
|
85
|
+
</Link>
|
|
86
|
+
</li>
|
|
87
|
+
))}
|
|
88
|
+
</ul>
|
|
89
|
+
<h2>Resources</h2>
|
|
90
|
+
<ul>
|
|
91
|
+
{data.resources.map(resource => (
|
|
92
|
+
<li key={resource.url} className="remix__page__resource">
|
|
93
|
+
<a href={resource.url}>{resource.name}</a>
|
|
94
|
+
</li>
|
|
95
|
+
))}
|
|
96
|
+
</ul>
|
|
97
|
+
</aside>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Whoa whoa whoa, wait a sec...why are we overriding global CSS selectors?
|
|
3
|
+
* Isn't that kind of scary? How do we know this won't have side effects?
|
|
4
|
+
*
|
|
5
|
+
* In Remix, CSS that is included in a route file will *only* show up on that
|
|
6
|
+
* route (and for nested routes, its children). When the user navigates away
|
|
7
|
+
* from that route the CSS files linked from those routes will be automatically
|
|
8
|
+
* unloaded, making your styles much easier to predict and control.
|
|
9
|
+
*
|
|
10
|
+
* Read more about styling routes in the docs:
|
|
11
|
+
* https://remix.run/guides/styling
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
:root {
|
|
15
|
+
--color-foreground: hsl(0, 0%, 7%);
|
|
16
|
+
--color-background: hsl(56, 100%, 50%);
|
|
17
|
+
--color-links: hsl(345, 56%, 39%);
|
|
18
|
+
--color-links-hover: hsl(345, 51%, 49%);
|
|
19
|
+
--color-border: rgb(184, 173, 20);
|
|
20
|
+
--font-body: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
21
|
+
Liberation Mono, Courier New, monospace;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.about__intro {
|
|
25
|
+
max-width: 500px;
|
|
26
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* You can just delete everything here or keep whatever you like, it's just a
|
|
3
|
+
* quick baseline!
|
|
4
|
+
*/
|
|
5
|
+
:root {
|
|
6
|
+
--color-foreground: hsl(0, 0%, 7%);
|
|
7
|
+
--color-background: hsl(0, 0%, 100%);
|
|
8
|
+
--color-links: hsl(213, 100%, 52%);
|
|
9
|
+
--color-links-hover: hsl(213, 100%, 43%);
|
|
10
|
+
--color-border: hsl(0, 0%, 82%);
|
|
11
|
+
--font-body: -apple-system, "Segoe UI", Helvetica Neue, Helvetica, Roboto,
|
|
12
|
+
Arial, sans-serif, system-ui, "Apple Color Emoji", "Segoe UI Emoji";
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
html {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
*,
|
|
20
|
+
*::before,
|
|
21
|
+
*::after {
|
|
22
|
+
box-sizing: inherit;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:-moz-focusring {
|
|
26
|
+
outline: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:focus {
|
|
30
|
+
outline: var(--color-links) solid 2px;
|
|
31
|
+
outline-offset: 2px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
html,
|
|
35
|
+
body {
|
|
36
|
+
padding: 0;
|
|
37
|
+
margin: 0;
|
|
38
|
+
background-color: var(--color-background);
|
|
39
|
+
color: var(--color-foreground);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
body {
|
|
43
|
+
font-family: var(--font-body);
|
|
44
|
+
line-height: 1.5;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
a {
|
|
48
|
+
color: var(--color-links);
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
a:hover {
|
|
53
|
+
color: var(--color-links-hover);
|
|
54
|
+
text-decoration: underline;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
hr {
|
|
58
|
+
display: block;
|
|
59
|
+
height: 1px;
|
|
60
|
+
border: 0;
|
|
61
|
+
background-color: var(--color-border);
|
|
62
|
+
margin-top: 2rem;
|
|
63
|
+
margin-bottom: 2rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
input:where([type="text"]),
|
|
67
|
+
input:where([type="search"]) {
|
|
68
|
+
display: block;
|
|
69
|
+
border: 1px solid var(--color-border);
|
|
70
|
+
width: 100%;
|
|
71
|
+
font: inherit;
|
|
72
|
+
line-height: 1;
|
|
73
|
+
height: calc(1ch + 1.5em);
|
|
74
|
+
padding-right: 0.5em;
|
|
75
|
+
padding-left: 0.5em;
|
|
76
|
+
background-color: hsl(0 0% 100% / 20%);
|
|
77
|
+
color: var(--color-foreground);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.sr-only {
|
|
81
|
+
position: absolute;
|
|
82
|
+
width: 1px;
|
|
83
|
+
height: 1px;
|
|
84
|
+
padding: 0;
|
|
85
|
+
margin: -1px;
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
clip: rect(0, 0, 0, 0);
|
|
88
|
+
white-space: nowrap;
|
|
89
|
+
border-width: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.container {
|
|
93
|
+
--gutter: 16px;
|
|
94
|
+
width: 1024px;
|
|
95
|
+
max-width: calc(100% - var(--gutter) * 2);
|
|
96
|
+
margin-right: auto;
|
|
97
|
+
margin-left: auto;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.remix-app {
|
|
101
|
+
display: flex;
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
min-height: 100vh;
|
|
104
|
+
min-height: calc(100vh - env(safe-area-inset-bottom));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.remix-app > * {
|
|
108
|
+
width: 100%;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.remix-app__header {
|
|
112
|
+
padding-top: 1rem;
|
|
113
|
+
padding-bottom: 1rem;
|
|
114
|
+
border-bottom: 1px solid var(--color-border);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.remix-app__header-content {
|
|
118
|
+
display: flex;
|
|
119
|
+
justify-content: space-between;
|
|
120
|
+
align-items: center;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.remix-app__header-home-link {
|
|
124
|
+
width: 106px;
|
|
125
|
+
height: 30px;
|
|
126
|
+
color: var(--color-foreground);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.remix-app__header-nav ul {
|
|
130
|
+
list-style: none;
|
|
131
|
+
margin: 0;
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
gap: 1.5em;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.remix-app__header-nav li {
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.remix-app__main {
|
|
142
|
+
flex: 1 1 100%;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.remix-app__footer {
|
|
146
|
+
padding-top: 1rem;
|
|
147
|
+
padding-bottom: 1rem;
|
|
148
|
+
border-top: 1px solid var(--color-border);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.remix-app__footer-content {
|
|
152
|
+
display: flex;
|
|
153
|
+
justify-content: center;
|
|
154
|
+
align-items: center;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.remix__page {
|
|
158
|
+
--gap: 1rem;
|
|
159
|
+
--space: 2rem;
|
|
160
|
+
display: grid;
|
|
161
|
+
grid-auto-rows: min-content;
|
|
162
|
+
gap: var(--gap);
|
|
163
|
+
padding-top: var(--space);
|
|
164
|
+
padding-bottom: var(--space);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@media print, screen and (min-width: 640px) {
|
|
168
|
+
.remix__page {
|
|
169
|
+
--gap: 2rem;
|
|
170
|
+
grid-auto-rows: unset;
|
|
171
|
+
grid-template-columns: repeat(2, 1fr);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@media screen and (min-width: 1024px) {
|
|
176
|
+
.remix__page {
|
|
177
|
+
--gap: 4rem;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.remix__page > main > :first-child {
|
|
182
|
+
margin-top: 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.remix__page > main > :last-child {
|
|
186
|
+
margin-bottom: 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.remix__page > aside {
|
|
190
|
+
margin: 0;
|
|
191
|
+
padding: 1.5ch 2ch;
|
|
192
|
+
border: solid 1px var(--color-border);
|
|
193
|
+
border-radius: 0.5rem;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.remix__page > aside > :first-child {
|
|
197
|
+
margin-top: 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.remix__page > aside > :last-child {
|
|
201
|
+
margin-bottom: 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.remix__form {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
gap: 1rem;
|
|
208
|
+
padding: 1rem;
|
|
209
|
+
border: 1px solid var(--color-border);
|
|
210
|
+
border-radius: 0.5rem;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.remix__form > * {
|
|
214
|
+
margin-top: 0;
|
|
215
|
+
margin-bottom: 0;
|
|
216
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"name": "<%= projectName %>",
|
|
4
|
+
"description": "",
|
|
5
|
+
"license": "",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "remix build",
|
|
8
|
+
"dev": "remix dev",
|
|
9
|
+
"postinstall": "remix setup node",
|
|
10
|
+
"start": "remix-serve build"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@remix-run/react": "^1.0.6",
|
|
14
|
+
"react": "^17.0.2",
|
|
15
|
+
"react-dom": "^17.0.2",
|
|
16
|
+
"remix": "^1.0.6",
|
|
17
|
+
"@remix-run/serve": "^1.0.6"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@remix-run/dev": "^1.0.6",
|
|
21
|
+
"@types/react": "^17.0.24",
|
|
22
|
+
"@types/react-dom": "^17.0.9",
|
|
23
|
+
"typescript": "^4.1.2"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=14"
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false
|
|
29
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"resolveJsonModule": true,
|
|
10
|
+
"target": "ES2019",
|
|
11
|
+
"strict": true,
|
|
12
|
+
|
|
13
|
+
// Remix takes care of building everything in `remix build`.
|
|
14
|
+
"noEmit": true
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { NxRemixGeneratorSchema } from '../schema';
|
|
2
|
+
import { Tree } from '@nrwl/devkit';
|
|
3
|
+
export interface NormalizedSchema extends NxRemixGeneratorSchema {
|
|
4
|
+
projectName: string;
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
parsedTags: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function normalizeOptions(tree: Tree, options: NxRemixGeneratorSchema): NormalizedSchema;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeOptions = void 0;
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
function normalizeOptions(tree, options) {
|
|
6
|
+
const name = (0, devkit_1.names)(options.project).fileName;
|
|
7
|
+
const projectName = name;
|
|
8
|
+
const projectRoot = `packages/${name}`;
|
|
9
|
+
const parsedTags = options.tags
|
|
10
|
+
? options.tags.split(',').map((s) => s.trim())
|
|
11
|
+
: [];
|
|
12
|
+
return Object.assign(Object.assign({}, options), { projectName,
|
|
13
|
+
projectRoot,
|
|
14
|
+
parsedTags });
|
|
15
|
+
}
|
|
16
|
+
exports.normalizeOptions = normalizeOptions;
|
|
17
|
+
//# sourceMappingURL=normalize-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize-options.js","sourceRoot":"","sources":["../../../../../../../packages/nx-remix/src/generators/preset/lib/normalize-options.ts"],"names":[],"mappings":";;;AACA,yCAA2C;AAQ3C,SAAgB,gBAAgB,CAC9B,IAAU,EACV,OAA+B;IAE/B,MAAM,IAAI,GAAG,IAAA,cAAK,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,WAAW,GAAG,YAAY,IAAI,EAAE,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI;QAC7B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,CAAC,CAAC,EAAE,CAAC;IAEP,uCACK,OAAO,KACV,WAAW;QACX,WAAW;QACX,UAAU,IACV;AACJ,CAAC;AAjBD,4CAiBC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const devkit_1 = require("@nrwl/devkit");
|
|
5
|
+
const normalize_options_1 = require("./lib/normalize-options");
|
|
6
|
+
const application_impl_1 = require("../application/application.impl");
|
|
7
|
+
function default_1(tree, _options) {
|
|
8
|
+
return (0, tslib_1.__awaiter)(this, void 0, void 0, function* () {
|
|
9
|
+
const options = (0, normalize_options_1.normalizeOptions)(tree, _options);
|
|
10
|
+
const workspaceConfig = (0, devkit_1.readWorkspaceConfiguration)(tree);
|
|
11
|
+
workspaceConfig.workspaceLayout = {
|
|
12
|
+
appsDir: 'packages',
|
|
13
|
+
libsDir: 'packages',
|
|
14
|
+
};
|
|
15
|
+
(0, devkit_1.updateWorkspaceConfiguration)(tree, workspaceConfig);
|
|
16
|
+
const task = yield (0, application_impl_1.default)(tree, {
|
|
17
|
+
name: options.projectName,
|
|
18
|
+
tags: options.tags,
|
|
19
|
+
skipFormat: true,
|
|
20
|
+
});
|
|
21
|
+
tree.delete('apps');
|
|
22
|
+
tree.delete('libs');
|
|
23
|
+
yield (0, devkit_1.formatFiles)(tree);
|
|
24
|
+
return task;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.default = default_1;
|
|
28
|
+
//# sourceMappingURL=preset.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.impl.js","sourceRoot":"","sources":["../../../../../../packages/nx-remix/src/generators/preset/preset.impl.ts"],"names":[],"mappings":";;;AAAA,yCAKsB;AAGtB,+DAA2D;AAC3D,sEAAmE;AAEnE,mBAA+B,IAAU,EAAE,QAAgC;;QACzE,MAAM,OAAO,GAAG,IAAA,oCAAgB,EAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEjD,MAAM,eAAe,GAAG,IAAA,mCAA0B,EAAC,IAAI,CAAC,CAAC;QACzD,eAAe,CAAC,eAAe,GAAG;YAChC,OAAO,EAAE,UAAU;YACnB,OAAO,EAAE,UAAU;SACpB,CAAC;QACF,IAAA,qCAA4B,EAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAEpD,MAAM,IAAI,GAAG,MAAM,IAAA,0BAAoB,EAAC,IAAI,EAAE;YAC5C,IAAI,EAAE,OAAO,CAAC,WAAW;YACzB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEpB,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAC;QAExB,OAAO,IAAI,CAAC;IACd,CAAC;CAAA;AAtBD,4BAsBC"}
|