~repos /edge-city
git clone https://pyrossh.dev/repos/edge-city.git
edge-city is a next level meta-framework for react that runs only on edge runtimes
6b0984a3
—
pyrossh 2 years ago
improve todos
- cli.js +4 -6
- example/package.json +4 -6
- example/src/components/Counter/Counter.css +9 -0
- example/src/components/Counter/Counter.jsx +11 -3
- example/src/components/Layout/Layout.css +2 -0
- example/src/components/Layout/Layout.jsx +0 -1
- example/src/components/Todo/Todo.css +27 -11
- example/src/components/Todo/Todo.jsx +55 -82
- example/src/pages/app.css +387 -0
- example/src/pages/app.jsx +1 -0
- example/src/pages/page.jsx +1 -1
- example/src/pages/todos/page.css +52 -1
- example/src/pages/todos/page.jsx +27 -18
- pnpm-lock.yaml +0 -15
cli.js
CHANGED
|
@@ -35,7 +35,6 @@ const recordSize = (buildStart, dest) => {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
let generatedCss = ``;
|
|
38
|
-
const cssCache = [];
|
|
39
38
|
const serverEnvs = Object.keys(process.env)
|
|
40
39
|
.filter((k) => k.startsWith("EDGE_") || k === "NODE_ENV")
|
|
41
40
|
.reduce((acc, k) => {
|
|
@@ -130,11 +129,8 @@ const bundlePages = async () => {
|
|
|
130
129
|
}
|
|
131
130
|
});
|
|
132
131
|
build.onLoad({ filter: /\\*.css/, namespace: undefined }, (args) => {
|
|
133
|
-
if (!cssCache[args.path]) {
|
|
134
|
-
|
|
132
|
+
const css = fs.readFileSync(args.path);
|
|
135
|
-
|
|
133
|
+
generatedCss += css + "\n\n";
|
|
136
|
-
cssCache[args.path] = true;
|
|
137
|
-
}
|
|
138
134
|
return {
|
|
139
135
|
contents: "",
|
|
140
136
|
loader: "file",
|
|
@@ -269,7 +265,9 @@ const build = async (platform, setProd) => {
|
|
|
269
265
|
await bundleCss();
|
|
270
266
|
if (!setProd) {
|
|
271
267
|
// watch src files, imports and dotenv
|
|
268
|
+
console.log("watching for changes");
|
|
272
269
|
watch(srcDir, { recursive: true }, async (evt, name) => {
|
|
270
|
+
generatedCss = "";
|
|
273
271
|
await bundlePages();
|
|
274
272
|
await bundleServices();
|
|
275
273
|
await bundleCss();
|
example/package.json
CHANGED
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@neondatabase/serverless": "0.4.5",
|
|
16
16
|
"drizzle-orm": "0.26.0",
|
|
17
|
-
"modern-normalize": "^2.0.0",
|
|
18
|
-
"normalize.css": "^8.0.1",
|
|
19
17
|
"edge-city": "workspace:*",
|
|
20
18
|
"react": "18.2.0",
|
|
21
19
|
"react-aria-components": "1.0.0-alpha.3",
|
|
@@ -27,12 +25,12 @@
|
|
|
27
25
|
"zod": "^3.21.4"
|
|
28
26
|
},
|
|
29
27
|
"devDependencies": {
|
|
30
|
-
"drizzle-kit": "0.18.0",
|
|
31
|
-
"postgres": "3.3.4",
|
|
32
28
|
"@playwright/test": "^1.31.2",
|
|
29
|
+
"drizzle-kit": "0.18.0",
|
|
33
30
|
"eslint": "^8.35.0",
|
|
34
|
-
"wrangler": "3.0.1",
|
|
35
|
-
"eslint-config-react-app": "^7.0.1"
|
|
31
|
+
"eslint-config-react-app": "^7.0.1",
|
|
32
|
+
"postgres": "3.3.4",
|
|
33
|
+
"wrangler": "3.0.1"
|
|
36
34
|
},
|
|
37
35
|
"prettier": {
|
|
38
36
|
"printWidth": 120
|
example/src/components/Counter/Counter.css
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
.counter {
|
|
2
|
+
& .button {
|
|
3
|
+
border-radius: 0.25rem;
|
|
4
|
+
padding: 1rem;
|
|
5
|
+
background-color: #2563eb;
|
|
6
|
+
color: white;
|
|
7
|
+
margin-left: 0.5rem;
|
|
8
|
+
}
|
|
9
|
+
}
|
example/src/components/Counter/Counter.jsx
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
|
+
import { Button } from 'react-aria-components';
|
|
3
|
+
import "./Counter.css";
|
|
2
4
|
|
|
3
5
|
const Counter = () => {
|
|
4
6
|
const [count, setCount] = useState(5);
|
|
7
|
+
const increment = () => setCount(count - 1);
|
|
8
|
+
const decrement = () => setCount(count + 1);
|
|
5
9
|
return (
|
|
6
|
-
<div>
|
|
10
|
+
<div className="counter">
|
|
7
|
-
<button onClick={
|
|
11
|
+
<Button className="button" onClick={increment}>
|
|
12
|
+
-
|
|
13
|
+
</Button>
|
|
8
14
|
<span className="count">
|
|
9
15
|
{count}
|
|
10
16
|
</span>
|
|
11
|
-
<button onClick={
|
|
17
|
+
<Button className="button" onClick={decrement}>
|
|
18
|
+
+
|
|
19
|
+
</Button>
|
|
12
20
|
</div>
|
|
13
21
|
)
|
|
14
22
|
}
|
example/src/components/Layout/Layout.css
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
& .content {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex: 1;
|
|
20
22
|
padding: 20px;
|
|
21
23
|
padding-bottom: 50px;
|
|
22
24
|
border-left: 2px solid #eee;
|
example/src/components/Layout/Layout.jsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Link } from "edge-city";
|
|
3
|
-
import "modern-normalize";
|
|
4
3
|
import "./Layout.css";
|
|
5
4
|
|
|
6
5
|
const Layout = ({ children }) => {
|
example/src/components/Todo/Todo.css
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
.todo {
|
|
2
|
-
& label {
|
|
3
|
-
list-style-type: none;
|
|
4
|
-
|
|
2
|
+
display: flex;
|
|
5
|
-
|
|
3
|
+
border-bottom-width: 1px;
|
|
6
|
-
|
|
4
|
+
border-color: #d1d5db;
|
|
5
|
+
align-items: center;
|
|
6
|
+
height: 4rem;
|
|
7
|
+
margin-bottom: 0.5rem;
|
|
7
|
-
|
|
8
|
+
margin-top: 0.5rem;
|
|
9
|
+
|
|
10
|
+
& .text {
|
|
8
11
|
display: flex;
|
|
12
|
+
flex: 1;
|
|
9
|
-
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
|
|
10
|
-
|
|
15
|
+
margin-left: 0.5rem;
|
|
11
16
|
}
|
|
12
|
-
|
|
17
|
+
|
|
13
|
-
& .
|
|
18
|
+
& .timestamp {
|
|
19
|
+
line-height: 2;
|
|
20
|
+
opacity: 0.5;
|
|
14
|
-
|
|
21
|
+
font-size: 0.75rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
& .edit-button {
|
|
25
|
+
padding: 0.5rem;
|
|
26
|
+
margin-right: 0.5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
& .delete-button {
|
|
30
|
+
padding: 0.5rem;
|
|
15
31
|
}
|
|
16
32
|
}
|
example/src/components/Todo/Todo.jsx
CHANGED
|
@@ -1,94 +1,67 @@
|
|
|
1
|
-
import { useState } from "react";
|
|
1
|
+
import { useState, useCallback } from "react";
|
|
2
|
-
// import PropTypes from 'prop-types';
|
|
3
|
-
// import { Button, InputGroup } from "@blueprintjs/core";
|
|
4
|
-
// import useMutation from '@/hooks/useMutation';
|
|
5
|
-
// import { TodoPropType } from '@/models/Todo';
|
|
6
2
|
import "./Todo.css";
|
|
7
3
|
|
|
8
|
-
// const propTypes = {
|
|
9
|
-
|
|
4
|
+
const Todo = ({ item, updateMutation, deleteMutation }) => {
|
|
10
|
-
|
|
5
|
+
const [editing, setEditing] = useState(false);
|
|
11
|
-
|
|
12
|
-
const
|
|
6
|
+
const doSave = useCallback(() => {
|
|
7
|
+
if (!input.current) return;
|
|
8
|
+
setBusy(true);
|
|
13
|
-
|
|
9
|
+
save(item, input.current.value, item.completed);
|
|
10
|
+
}, [item]);
|
|
14
|
-
|
|
11
|
+
const cancelEdit = useCallback(() => {
|
|
15
|
-
|
|
12
|
+
if (!input.current) return;
|
|
13
|
+
setEditing(false);
|
|
16
|
-
|
|
14
|
+
input.current.value = item.text;
|
|
17
|
-
|
|
15
|
+
}, []);
|
|
18
|
-
|
|
16
|
+
const doDelete = useCallback(() => {
|
|
17
|
+
const yes = confirm("Are you sure you want to delete this item?");
|
|
18
|
+
if (!yes) return;
|
|
19
|
+
setBusy(true);
|
|
20
|
+
save(item, null, item.completed);
|
|
21
|
+
}, [item]);
|
|
22
|
+
const doSaveCompleted = useCallback((completed) => {
|
|
23
|
+
setBusy(true);
|
|
19
|
-
|
|
24
|
+
save(item, item.text, completed);
|
|
20
|
-
// await refetch();
|
|
21
|
-
|
|
25
|
+
}, [item]);
|
|
22
26
|
return (
|
|
23
27
|
<li className="todo">
|
|
24
|
-
{!
|
|
28
|
+
{!editing && (
|
|
25
|
-
<
|
|
29
|
+
<>
|
|
26
|
-
<input
|
|
27
|
-
|
|
30
|
+
<input type="checkbox" />
|
|
28
|
-
checked={todo.completed}
|
|
29
|
-
onChange={(e) => {
|
|
30
|
-
// updateMutation.mutate({ completed: e.target.checked })
|
|
31
|
-
}}
|
|
32
|
-
|
|
31
|
+
<div class="text">
|
|
32
|
+
<p>{item.text}</p>
|
|
33
|
-
|
|
33
|
+
<p className="timestamp">{item.createdAt}</p>
|
|
34
|
-
|
|
34
|
+
</div>
|
|
35
|
-
)}
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
<button className="edit-button" title="Edit">✏️</button>
|
|
38
|
-
<InputGroup
|
|
39
|
-
autoFocus
|
|
40
|
-
value={state.text}
|
|
41
|
-
|
|
36
|
+
<button class="delete-button" title="Delete">🗑️</button>
|
|
42
|
-
onKeyDown={async (e) => {
|
|
43
|
-
if (e.key === "Enter") {
|
|
44
|
-
await updateMutation.mutate({ text: state.text });
|
|
45
|
-
setState({ text: todo.text, editing: false });
|
|
46
|
-
} else if (e.key === "Escape") {
|
|
47
|
-
setState({ text: todo.text, editing: false });
|
|
48
|
-
}
|
|
49
|
-
}}
|
|
50
|
-
/>
|
|
37
|
+
</>
|
|
51
38
|
)}
|
|
52
|
-
|
|
39
|
+
{editing && (
|
|
53
|
-
|
|
40
|
+
<>
|
|
41
|
+
<input
|
|
54
|
-
|
|
42
|
+
class="border rounded w-full py-2 px-3 mr-4"
|
|
43
|
+
defaultValue={item.text}
|
|
44
|
+
/>
|
|
55
|
-
<
|
|
45
|
+
<button
|
|
56
|
-
|
|
46
|
+
class="p-2 rounded mr-2 disabled:opacity-50"
|
|
57
|
-
>
|
|
58
|
-
Edit
|
|
59
|
-
|
|
47
|
+
title="Save"
|
|
60
|
-
)}
|
|
61
|
-
|
|
62
|
-
{todo.completed && (
|
|
63
|
-
<Button loading={deleteMutation.isMutating} onClick={deleteMutation.mutate}>
|
|
64
|
-
Delete
|
|
65
|
-
</Button>
|
|
66
|
-
)}
|
|
67
|
-
|
|
68
|
-
{state.editing && state.text !== todo.text && (
|
|
69
|
-
<Button
|
|
70
|
-
loading={updateMutation.isMutating}
|
|
71
|
-
onClick={
|
|
48
|
+
onClick={doSave}
|
|
72
|
-
await updateMutation.mutate({ text: state.text });
|
|
73
|
-
|
|
49
|
+
disabled={busy}
|
|
74
|
-
}}
|
|
75
50
|
>
|
|
76
|
-
|
|
51
|
+
💾
|
|
77
|
-
</
|
|
52
|
+
</button>
|
|
78
|
-
)}
|
|
79
|
-
|
|
80
|
-
{state.editing && (
|
|
81
|
-
<
|
|
53
|
+
<button
|
|
82
|
-
|
|
54
|
+
class="p-2 rounded disabled:opacity-50"
|
|
55
|
+
title="Cancel"
|
|
56
|
+
onClick={cancelEdit}
|
|
57
|
+
disabled={busy}
|
|
83
58
|
>
|
|
84
|
-
|
|
59
|
+
🚫
|
|
85
|
-
</
|
|
60
|
+
</button>
|
|
61
|
+
</>
|
|
86
|
-
|
|
62
|
+
)}
|
|
87
|
-
</span> */}
|
|
88
63
|
</li>
|
|
89
64
|
);
|
|
90
65
|
};
|
|
91
66
|
|
|
92
|
-
// Todo.propTypes = propTypes;
|
|
93
|
-
|
|
94
67
|
export default Todo;
|
example/src/pages/app.css
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/*
|
|
2
|
+
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
3
|
+
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
*,
|
|
7
|
+
::before,
|
|
8
|
+
::after {
|
|
9
|
+
box-sizing: border-box; /* 1 */
|
|
10
|
+
border-width: 0; /* 2 */
|
|
11
|
+
border-style: solid; /* 2 */
|
|
12
|
+
border-color: theme('borderColor.DEFAULT', currentColor); /* 2 */
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
::before,
|
|
16
|
+
::after {
|
|
17
|
+
--tw-content: '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
1. Use a consistent sensible line-height in all browsers.
|
|
22
|
+
2. Prevent adjustments of font size after orientation changes in iOS.
|
|
23
|
+
3. Use a more readable tab size.
|
|
24
|
+
4. Use the user's configured `sans` font-family by default.
|
|
25
|
+
5. Use the user's configured `sans` font-feature-settings by default.
|
|
26
|
+
6. Use the user's configured `sans` font-variation-settings by default.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
html {
|
|
30
|
+
line-height: 1.5; /* 1 */
|
|
31
|
+
-webkit-text-size-adjust: 100%; /* 2 */
|
|
32
|
+
-moz-tab-size: 4; /* 3 */
|
|
33
|
+
tab-size: 4; /* 3 */
|
|
34
|
+
font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */
|
|
35
|
+
font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */
|
|
36
|
+
font-variation-settings: theme('fontFamily.sans[1].fontVariationSettings', normal); /* 6 */
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
1. Remove the margin in all browsers.
|
|
41
|
+
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
body {
|
|
45
|
+
margin: 0; /* 1 */
|
|
46
|
+
line-height: inherit; /* 2 */
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/*
|
|
50
|
+
1. Add the correct height in Firefox.
|
|
51
|
+
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
|
52
|
+
3. Ensure horizontal rules are visible by default.
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
hr {
|
|
56
|
+
height: 0; /* 1 */
|
|
57
|
+
color: inherit; /* 2 */
|
|
58
|
+
border-top-width: 1px; /* 3 */
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
Add the correct text decoration in Chrome, Edge, and Safari.
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
abbr:where([title]) {
|
|
66
|
+
text-decoration: underline dotted;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
Remove the default font size and weight for headings.
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
h1,
|
|
74
|
+
h2,
|
|
75
|
+
h3,
|
|
76
|
+
h4,
|
|
77
|
+
h5,
|
|
78
|
+
h6 {
|
|
79
|
+
font-size: inherit;
|
|
80
|
+
font-weight: inherit;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/*
|
|
84
|
+
Reset links to optimize for opt-in styling instead of opt-out.
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
a {
|
|
88
|
+
color: inherit;
|
|
89
|
+
text-decoration: inherit;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/*
|
|
93
|
+
Add the correct font weight in Edge and Safari.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
b,
|
|
97
|
+
strong {
|
|
98
|
+
font-weight: bolder;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
1. Use the user's configured `mono` font family by default.
|
|
103
|
+
2. Correct the odd `em` font sizing in all browsers.
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
code,
|
|
107
|
+
kbd,
|
|
108
|
+
samp,
|
|
109
|
+
pre {
|
|
110
|
+
font-family: theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); /* 1 */
|
|
111
|
+
font-size: 1em; /* 2 */
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
Add the correct font size in all browsers.
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
small {
|
|
119
|
+
font-size: 80%;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/*
|
|
123
|
+
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
sub,
|
|
127
|
+
sup {
|
|
128
|
+
font-size: 75%;
|
|
129
|
+
line-height: 0;
|
|
130
|
+
position: relative;
|
|
131
|
+
vertical-align: baseline;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
sub {
|
|
135
|
+
bottom: -0.25em;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
sup {
|
|
139
|
+
top: -0.5em;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
|
144
|
+
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
|
145
|
+
3. Remove gaps between table borders by default.
|
|
146
|
+
*/
|
|
147
|
+
|
|
148
|
+
table {
|
|
149
|
+
text-indent: 0; /* 1 */
|
|
150
|
+
border-color: inherit; /* 2 */
|
|
151
|
+
border-collapse: collapse; /* 3 */
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
1. Change the font styles in all browsers.
|
|
156
|
+
2. Remove the margin in Firefox and Safari.
|
|
157
|
+
3. Remove default padding in all browsers.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
button,
|
|
161
|
+
input,
|
|
162
|
+
optgroup,
|
|
163
|
+
select,
|
|
164
|
+
textarea {
|
|
165
|
+
font-family: inherit; /* 1 */
|
|
166
|
+
font-size: 100%; /* 1 */
|
|
167
|
+
font-weight: inherit; /* 1 */
|
|
168
|
+
line-height: inherit; /* 1 */
|
|
169
|
+
color: inherit; /* 1 */
|
|
170
|
+
margin: 0; /* 2 */
|
|
171
|
+
padding: 0; /* 3 */
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/*
|
|
175
|
+
Remove the inheritance of text transform in Edge and Firefox.
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
button,
|
|
179
|
+
select {
|
|
180
|
+
text-transform: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/*
|
|
184
|
+
1. Correct the inability to style clickable types in iOS and Safari.
|
|
185
|
+
2. Remove default button styles.
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
button,
|
|
189
|
+
[type='button'],
|
|
190
|
+
[type='reset'],
|
|
191
|
+
[type='submit'] {
|
|
192
|
+
-webkit-appearance: button; /* 1 */
|
|
193
|
+
background-color: transparent; /* 2 */
|
|
194
|
+
background-image: none; /* 2 */
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/*
|
|
198
|
+
Use the modern Firefox focus style for all focusable elements.
|
|
199
|
+
*/
|
|
200
|
+
|
|
201
|
+
:-moz-focusring {
|
|
202
|
+
outline: auto;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/*
|
|
206
|
+
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
:-moz-ui-invalid {
|
|
210
|
+
box-shadow: none;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/*
|
|
214
|
+
Add the correct vertical alignment in Chrome and Firefox.
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
progress {
|
|
218
|
+
vertical-align: baseline;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/*
|
|
222
|
+
Correct the cursor style of increment and decrement buttons in Safari.
|
|
223
|
+
*/
|
|
224
|
+
|
|
225
|
+
::-webkit-inner-spin-button,
|
|
226
|
+
::-webkit-outer-spin-button {
|
|
227
|
+
height: auto;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
1. Correct the odd appearance in Chrome and Safari.
|
|
232
|
+
2. Correct the outline style in Safari.
|
|
233
|
+
*/
|
|
234
|
+
|
|
235
|
+
[type='search'] {
|
|
236
|
+
-webkit-appearance: textfield; /* 1 */
|
|
237
|
+
outline-offset: -2px; /* 2 */
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/*
|
|
241
|
+
Remove the inner padding in Chrome and Safari on macOS.
|
|
242
|
+
*/
|
|
243
|
+
|
|
244
|
+
::-webkit-search-decoration {
|
|
245
|
+
-webkit-appearance: none;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/*
|
|
249
|
+
1. Correct the inability to style clickable types in iOS and Safari.
|
|
250
|
+
2. Change font properties to `inherit` in Safari.
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
::-webkit-file-upload-button {
|
|
254
|
+
-webkit-appearance: button; /* 1 */
|
|
255
|
+
font: inherit; /* 2 */
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*
|
|
259
|
+
Add the correct display in Chrome and Safari.
|
|
260
|
+
*/
|
|
261
|
+
|
|
262
|
+
summary {
|
|
263
|
+
display: list-item;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/*
|
|
267
|
+
Removes the default spacing and border for appropriate elements.
|
|
268
|
+
*/
|
|
269
|
+
|
|
270
|
+
blockquote,
|
|
271
|
+
dl,
|
|
272
|
+
dd,
|
|
273
|
+
h1,
|
|
274
|
+
h2,
|
|
275
|
+
h3,
|
|
276
|
+
h4,
|
|
277
|
+
h5,
|
|
278
|
+
h6,
|
|
279
|
+
hr,
|
|
280
|
+
figure,
|
|
281
|
+
p,
|
|
282
|
+
pre {
|
|
283
|
+
margin: 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
fieldset {
|
|
287
|
+
margin: 0;
|
|
288
|
+
padding: 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
legend {
|
|
292
|
+
padding: 0;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
ol,
|
|
296
|
+
ul,
|
|
297
|
+
menu {
|
|
298
|
+
list-style: none;
|
|
299
|
+
margin: 0;
|
|
300
|
+
padding: 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
Prevent resizing textareas horizontally by default.
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
textarea {
|
|
308
|
+
resize: vertical;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/*
|
|
312
|
+
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
|
313
|
+
2. Set the default placeholder color to the user's configured gray 400 color.
|
|
314
|
+
*/
|
|
315
|
+
|
|
316
|
+
input::placeholder,
|
|
317
|
+
textarea::placeholder {
|
|
318
|
+
opacity: 1; /* 1 */
|
|
319
|
+
color: theme('colors.gray.400', #9ca3af); /* 2 */
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/*
|
|
323
|
+
Set the default cursor for buttons.
|
|
324
|
+
*/
|
|
325
|
+
|
|
326
|
+
button,
|
|
327
|
+
[role="button"] {
|
|
328
|
+
cursor: pointer;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/*
|
|
332
|
+
Make sure disabled buttons don't get the pointer cursor.
|
|
333
|
+
*/
|
|
334
|
+
:disabled {
|
|
335
|
+
cursor: default;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/*
|
|
339
|
+
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
|
340
|
+
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
|
341
|
+
This can trigger a poorly considered lint error in some tools but is included by design.
|
|
342
|
+
*/
|
|
343
|
+
|
|
344
|
+
img,
|
|
345
|
+
svg,
|
|
346
|
+
video,
|
|
347
|
+
canvas,
|
|
348
|
+
audio,
|
|
349
|
+
iframe,
|
|
350
|
+
embed,
|
|
351
|
+
object {
|
|
352
|
+
display: block; /* 1 */
|
|
353
|
+
vertical-align: middle; /* 2 */
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/*
|
|
357
|
+
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
|
358
|
+
*/
|
|
359
|
+
|
|
360
|
+
img,
|
|
361
|
+
video {
|
|
362
|
+
max-width: 100%;
|
|
363
|
+
height: auto;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Make elements with the HTML hidden attribute stay hidden by default */
|
|
367
|
+
[hidden] {
|
|
368
|
+
display: none;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
html {
|
|
372
|
+
line-height: 1.5;
|
|
373
|
+
font-size: 16px;
|
|
374
|
+
-webkit-text-size-adjust: 100%;
|
|
375
|
+
font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
body {
|
|
379
|
+
font-family: inherit;
|
|
380
|
+
line-height: inherit;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
h1 {
|
|
384
|
+
font-size: 1.25rem;
|
|
385
|
+
line-height: 1.75rem;
|
|
386
|
+
font-weight: 700;
|
|
387
|
+
}
|
example/src/pages/app.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SSRProvider } from 'react-aria';
|
|
2
2
|
import Layout from '@/components/Layout/Layout';
|
|
3
|
+
import "./app.css";
|
|
3
4
|
|
|
4
5
|
const App = ({ children }) => {
|
|
5
6
|
return (
|
example/src/pages/page.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { useRouter } from "edge-city";
|
|
3
3
|
import Counter from "@/components/Counter/Counter";
|
|
4
4
|
import { Helmet } from 'react-helmet-async';
|
example/src/pages/todos/page.css
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
|
+
.todos-page {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex: 1;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
max-width: 36rem;
|
|
6
|
+
|
|
7
|
+
& .title {
|
|
8
|
+
font-size: 1.25rem;
|
|
9
|
+
line-height: 1.75rem;
|
|
10
|
+
font-weight: 700;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
& .container {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
& .subtitle {
|
|
19
|
+
font-size: 0.875rem;
|
|
20
|
+
line-height: 1.25rem;
|
|
21
|
+
opacity: 0.5;
|
|
22
|
+
margin-top: 1rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
& form {
|
|
26
|
+
display: flex;
|
|
27
|
+
margin-top: 1rem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
& ul {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
& .add-button {
|
|
36
|
+
border-radius: 0.25rem;
|
|
37
|
+
padding: 0.5rem;
|
|
38
|
+
background-color: #2563eb;
|
|
39
|
+
color: white;
|
|
40
|
+
margin-left: 0.5rem;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
1
44
|
:root {
|
|
2
45
|
--spectrum-alias-border-color: black;
|
|
3
46
|
--spectrum-global-color-gray-50: white;
|
|
@@ -11,10 +54,10 @@
|
|
|
11
54
|
--text-color-disabled: var(--spectrum-alias-text-color-disabled);
|
|
12
55
|
--focus-ring-color: slateblue;
|
|
13
56
|
--invalid-color: var(--spectrum-global-color-red-600);
|
|
14
|
-
|
|
15
57
|
display: flex;
|
|
16
58
|
flex-direction: column;
|
|
17
59
|
width: fit-content;
|
|
60
|
+
flex: 1;
|
|
18
61
|
|
|
19
62
|
.react-aria-Input {
|
|
20
63
|
padding: 0.286rem;
|
|
@@ -24,6 +67,14 @@
|
|
|
24
67
|
background: var(--field-background);
|
|
25
68
|
font-size: 1.143rem;
|
|
26
69
|
color: var(--text-color);
|
|
70
|
+
border-radius: 0.25rem;
|
|
71
|
+
margin-right: 1rem;
|
|
72
|
+
border-width: 1px;
|
|
73
|
+
width: 100%;
|
|
74
|
+
padding-left: 0.75rem;
|
|
75
|
+
padding-right: 0.75rem;
|
|
76
|
+
padding-bottom: 0.5rem;
|
|
77
|
+
padding-top: 0.5rem;
|
|
27
78
|
|
|
28
79
|
&[aria-invalid] {
|
|
29
80
|
border-color: var(--invalid-color);
|
example/src/pages/todos/page.jsx
CHANGED
|
@@ -2,10 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { Helmet } from 'react-helmet-async';
|
|
3
3
|
import { useQuery, useMutation } from "edge-city";
|
|
4
4
|
import { useForm } from 'react-hook-form';
|
|
5
|
+
import { Button, TextField, Input } from 'react-aria-components';
|
|
5
6
|
import Todo from "@/components/Todo/Todo";
|
|
6
|
-
import { TextField, Label, Input } from 'react-aria-components';
|
|
7
|
-
import { Button } from 'react-aria-components';
|
|
8
|
-
import { getTodos, createTodo } from "@/services/todos.service";
|
|
7
|
+
import { getTodos, createTodo, updateTodo, deleteTodo } from "@/services/todos.service";
|
|
9
8
|
import "./page.css";
|
|
10
9
|
|
|
11
10
|
const Page = () => {
|
|
@@ -17,30 +16,40 @@ const Page = () => {
|
|
|
17
16
|
})
|
|
18
17
|
await refetch();
|
|
19
18
|
});
|
|
19
|
+
const updateMutation = useMutation(async ({ text, completed }) => {
|
|
20
|
+
await updateTodo({ text, completed });
|
|
21
|
+
await refetch();
|
|
22
|
+
});
|
|
23
|
+
const deleteMutation = useMutation(async (id) => {
|
|
24
|
+
await deleteTodo(id);
|
|
25
|
+
await refetch();
|
|
26
|
+
})
|
|
20
27
|
const { register, handleSubmit, formState: { errors } } = useForm();
|
|
21
28
|
return (
|
|
22
|
-
<div>
|
|
29
|
+
<div className="todos-page">
|
|
23
|
-
<h1>
|
|
30
|
+
<h1 className="title">Todo List</h1>
|
|
24
31
|
<Helmet>
|
|
25
|
-
<title>
|
|
32
|
+
<title>Todo List</title>
|
|
26
33
|
</Helmet>
|
|
27
|
-
<div>
|
|
28
|
-
<ul>
|
|
29
|
-
{data.map((item) => (
|
|
30
|
-
|
|
34
|
+
<div className="container">
|
|
31
|
-
))}
|
|
32
|
-
</
|
|
35
|
+
<p className="subtitle">Share this page to collaborate with others.</p>
|
|
33
36
|
<form onSubmit={handleSubmit(mutate)}>
|
|
34
37
|
<TextField isRequired isReadOnly={isMutating}>
|
|
35
|
-
<Label>Text (required)</Label>
|
|
36
|
-
<Input {...register('text')} />
|
|
38
|
+
<Input {...register('text')} placeholder="Add a todo item" />
|
|
37
39
|
{err?.text && <p>{err.text._errors[0]}</p>}
|
|
38
40
|
</TextField>
|
|
39
|
-
<Button type="submit" isDisabled={isMutating}>Add
|
|
41
|
+
<Button className="add-button" type="submit" isDisabled={isMutating}>Add</Button>
|
|
40
|
-
{isMutating && <div>
|
|
41
|
-
<p>Creating...</p>
|
|
42
|
-
</div>}
|
|
43
42
|
</form>
|
|
43
|
+
<ul>
|
|
44
|
+
{data.map((item) => (
|
|
45
|
+
<Todo
|
|
46
|
+
key={item.id}
|
|
47
|
+
item={item}
|
|
48
|
+
updateMutation={updateMutation}
|
|
49
|
+
deleteMutation={deleteMutation}
|
|
50
|
+
/>
|
|
51
|
+
))}
|
|
52
|
+
</ul>
|
|
44
53
|
</div>
|
|
45
54
|
</div>
|
|
46
55
|
)
|
pnpm-lock.yaml
CHANGED
|
@@ -95,12 +95,6 @@ importers:
|
|
|
95
95
|
edge-city:
|
|
96
96
|
specifier: workspace:*
|
|
97
97
|
version: link:..
|
|
98
|
-
modern-normalize:
|
|
99
|
-
specifier: ^2.0.0
|
|
100
|
-
version: 2.0.0
|
|
101
|
-
normalize.css:
|
|
102
|
-
specifier: ^8.0.1
|
|
103
|
-
version: 8.0.1
|
|
104
98
|
react:
|
|
105
99
|
specifier: 18.2.0
|
|
106
100
|
version: 18.2.0
|
|
@@ -7025,11 +7019,6 @@ packages:
|
|
|
7025
7019
|
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
|
7026
7020
|
dev: true
|
|
7027
7021
|
|
|
7028
|
-
/modern-normalize@2.0.0:
|
|
7029
|
-
resolution: {integrity: sha512-CxBoEVKh5U4DH3XuNbc5ONLF6dQBc8dSc7pdZ1957FGbIO5JBqGqqchhET9dTexri8/pk9xBL6+5ceOtCIp1QA==}
|
|
7030
|
-
engines: {node: '>=6'}
|
|
7031
|
-
dev: false
|
|
7032
|
-
|
|
7033
7022
|
/ms@2.1.2:
|
|
7034
7023
|
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
|
7035
7024
|
dev: true
|
|
@@ -7100,10 +7089,6 @@ packages:
|
|
|
7100
7089
|
engines: {node: '>=0.10.0'}
|
|
7101
7090
|
dev: true
|
|
7102
7091
|
|
|
7103
|
-
/normalize.css@8.0.1:
|
|
7104
|
-
resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==}
|
|
7105
|
-
dev: false
|
|
7106
|
-
|
|
7107
7092
|
/npm-run-path@4.0.1:
|
|
7108
7093
|
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
|
7109
7094
|
engines: {node: '>=8'}
|