~repos /edge-city

#react#js#ssr

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 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
- const css = fs.readFileSync(args.path);
132
+ const css = fs.readFileSync(args.path);
135
- generatedCss += css + "\n\n";
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={() => setCount(count - 1)}>-</button>
11
+ <Button className="button" onClick={increment}>
12
+ -
13
+ </Button>
8
14
  <span className="count">
9
15
  {count}
10
16
  </span>
11
- <button onClick={() => setCount(count + 1)}>+</button>
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
- padding: 1em;
2
+ display: flex;
5
- border-radius: 0.5em;
3
+ border-bottom-width: 1px;
6
- background-color: #ddd;
4
+ border-color: #d1d5db;
5
+ align-items: center;
6
+ height: 4rem;
7
+ margin-bottom: 0.5rem;
7
- margin-top: 1em;
8
+ margin-top: 0.5rem;
9
+
10
+ & .text {
8
11
  display: flex;
12
+ flex: 1;
9
- justify-content: space-between;
13
+ flex-direction: column;
14
+ font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;
10
- align-items: center;
15
+ margin-left: 0.5rem;
11
16
  }
12
-
17
+
13
- & .done {
18
+ & .timestamp {
19
+ line-height: 2;
20
+ opacity: 0.5;
14
- text-decoration: line-through;
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
- // // todo: PropTypes.shape(TodoPropType).isRequired,
4
+ const Todo = ({ item, updateMutation, deleteMutation }) => {
10
- // }
5
+ const [editing, setEditing] = useState(false);
11
-
12
- const Todo = ({ todo }) => {
6
+ const doSave = useCallback(() => {
7
+ if (!input.current) return;
8
+ setBusy(true);
13
- const [state, setState] = useState({ text: todo.text, editing: false });
9
+ save(item, input.current.value, item.completed);
10
+ }, [item]);
14
- // const updateMutation = useMutation(async (data) => {
11
+ const cancelEdit = useCallback(() => {
15
- // await onUpdate({ ...todo, ...data });
12
+ if (!input.current) return;
13
+ setEditing(false);
16
- // await refetch();
14
+ input.current.value = item.text;
17
- // });
15
+ }, []);
18
- // const deleteMutation = useMutation(async () => {
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
- // await onDelete(todo.id);
24
+ save(item, item.text, completed);
20
- // await refetch();
21
- // })
25
+ }, [item]);
22
26
  return (
23
27
  <li className="todo">
24
- {!state.editing && (
28
+ {!editing && (
25
- <label>
29
+ <>
26
- <input
27
- type="checkbox"
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
- <span className={todo.completed ? "done" : undefined}>{todo.text}</span>{" "}
33
+ <p className="timestamp">{item.createdAt}</p>
34
- </label>
34
+ </div>
35
- )}
36
-
37
- {/* {state.editing && (
35
+ <button className="edit-button" title="Edit">✏️</button>
38
- <InputGroup
39
- autoFocus
40
- value={state.text}
41
- onChange={(e) => setState({ text: e.target.value, editing: true })}
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
- <span>
40
+ <>
41
+ <input
54
- {!todo.completed && !state.editing && (
42
+ class="border rounded w-full py-2 px-3 mr-4"
43
+ defaultValue={item.text}
44
+ />
55
- <Button
45
+ <button
56
- onClick={() => setState({ text: todo.text, editing: true })}
46
+ class="p-2 rounded mr-2 disabled:opacity-50"
57
- >
58
- Edit
59
- </Button>
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={async () => {
48
+ onClick={doSave}
72
- await updateMutation.mutate({ text: state.text });
73
- setState({ text: todo.text, editing: false });
49
+ disabled={busy}
74
- }}
75
50
  >
76
- Save
51
+ 💾
77
- </Button>
52
+ </button>
78
- )}
79
-
80
- {state.editing && (
81
- <Button
53
+ <button
82
- onClick={() => setState({ text: todo.text, editing: false })}
54
+ class="p-2 rounded disabled:opacity-50"
55
+ title="Cancel"
56
+ onClick={cancelEdit}
57
+ disabled={busy}
83
58
  >
84
- Cancel
59
+ 🚫
85
- </Button>
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, { useEffect } from '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>Todos</h1>
30
+ <h1 className="title">Todo List</h1>
24
31
  <Helmet>
25
- <title>Todos</title>
32
+ <title>Todo List</title>
26
33
  </Helmet>
27
- <div>
28
- <ul>
29
- {data.map((item) => (
30
- <Todo key={item.id} todo={item} />
34
+ <div className="container">
31
- ))}
32
- </ul>
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 Todo</Button>
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'}