nextia 6.1.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/biome.json +21 -0
- package/package.json +13 -4
- package/src/bin.js +240 -0
- package/src/lib.js +2 -2
- package/template/README.md +29 -0
- package/template/_env.dev +4 -0
- package/template/_env.prod +1 -0
- package/template/_env.test +1 -0
- package/template/_gitignore +10 -0
- package/template/package.json +35 -0
- package/template/public/error.html +14 -0
- package/template/public/logo.svg +105 -0
- package/template/src/assets/i18n/index.js +26 -0
- package/template/src/assets/img/image.jpg +0 -0
- package/template/src/components/Counter/index.jsx +34 -0
- package/template/src/components/Counter/style.css +5 -0
- package/template/src/components/Message/index.jsx +12 -0
- package/template/src/components/index.js +10 -0
- package/template/src/components/ui/I18n/index.jsx +23 -0
- package/template/src/components/ui/Icon/index.jsx +50 -0
- package/template/src/components/ui/Link/index.jsx +12 -0
- package/template/src/components/ui/Svg/index.jsx +54 -0
- package/template/src/components/ui/Translate/index.jsx +18 -0
- package/template/src/index.html +18 -0
- package/template/src/index.jsx +4 -0
- package/template/src/pages/counter/functions.js +6 -0
- package/template/src/pages/counter/index.jsx +51 -0
- package/template/src/pages/counter/style.css +2 -0
- package/template/src/pages/env/functions.js +3 -0
- package/template/src/pages/env/index.jsx +27 -0
- package/template/src/pages/env/style.css +2 -0
- package/template/src/pages/functions.js +37 -0
- package/template/src/pages/home/functions.js +43 -0
- package/template/src/pages/home/index.jsx +211 -0
- package/template/src/pages/home/style.css +51 -0
- package/template/src/pages/http/not-found/index.jsx +10 -0
- package/template/src/pages/http/not-found/style.css +2 -0
- package/template/src/pages/icons/functions.js +3 -0
- package/template/src/pages/icons/index.jsx +20 -0
- package/template/src/pages/icons/style.css +5 -0
- package/template/src/pages/images/functions.js +3 -0
- package/template/src/pages/images/index.jsx +20 -0
- package/template/src/pages/images/style.css +8 -0
- package/template/src/pages/index.jsx +114 -0
- package/template/src/pages/mockapi/functions.js +71 -0
- package/template/src/pages/mockapi/index.jsx +101 -0
- package/template/src/pages/mockapi/style.css +57 -0
- package/template/src/pages/my-context/functions.js +7 -0
- package/template/src/pages/my-context/index.jsx +32 -0
- package/template/src/pages/my-context/style.css +2 -0
- package/template/src/pages/resize/functions.js +3 -0
- package/template/src/pages/resize/index.jsx +15 -0
- package/template/src/pages/resize/style.css +2 -0
- package/template/src/pages/search-params/functions.js +3 -0
- package/template/src/pages/search-params/index.jsx +36 -0
- package/template/src/pages/search-params/style.css +2 -0
- package/template/src/pages/subpage/hello/functions.js +3 -0
- package/template/src/pages/subpage/hello/index.jsx +11 -0
- package/template/src/pages/subpage/hello/style.css +2 -0
- package/template/src/pages/translate/functions.js +5 -0
- package/template/src/pages/translate/index.jsx +31 -0
- package/template/src/pages/translate/style.css +12 -0
- package/template/src/services/api.js +9 -0
- package/template/src/services/http.js +40 -0
- package/template/src/theme/animations.css +72 -0
- package/template/src/theme/fonts/Roboto-Regular.ttf +0 -0
- package/template/src/theme/fonts/index.css +7 -0
- package/template/src/theme/icons/exit.svg +69 -0
- package/template/src/theme/icons/icons.svg +126 -0
- package/template/src/theme/index.css +39 -0
- package/template/src/theme/util.css +27 -0
- package/template/src/utils/hooks.js +49 -0
- package/template/src/utils/index.js +19 -0
- package/template/test/index.test.js +12 -0
- package/template/vite.config.js +97 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { I18n, Icon, Link, Translate } from 'components'
|
|
2
|
+
import { PagesContext, useFx } from 'nextia'
|
|
3
|
+
import { lazy, useEffect, useRef, useState } from 'react'
|
|
4
|
+
import { startViewTransition, useQueryString, useResize } from 'utils'
|
|
5
|
+
import functions from './functions.js'
|
|
6
|
+
|
|
7
|
+
export default function Pages() {
|
|
8
|
+
const pagesContext = useFx(functions)
|
|
9
|
+
const { state, fx } = pagesContext
|
|
10
|
+
|
|
11
|
+
const [Page, setPage] = useState()
|
|
12
|
+
const qs = useQueryString()
|
|
13
|
+
const resize = useResize()
|
|
14
|
+
const ref = useRef()
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const hash = ['', '#/'].includes(qs.hash) ? '#/home' : qs.hash
|
|
18
|
+
|
|
19
|
+
const page = lazy(async () => {
|
|
20
|
+
const path = hash.substring(2).split('/')
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
if (path.length === 1) {
|
|
24
|
+
return await import(`./${path[0]}/index.jsx`)
|
|
25
|
+
} else if (path.length === 2) {
|
|
26
|
+
return await import(`./${path[0]}/${path[1]}/index.jsx`)
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.error(e)
|
|
30
|
+
return await import('./http/not-found/index.jsx')
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
startViewTransition(setPage(page), ref.current)
|
|
35
|
+
}, [qs.hash])
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<PagesContext value={pagesContext}>
|
|
39
|
+
<header style={{ display: 'flex', gap: '20px' }}>
|
|
40
|
+
<Icon id="globe" width="24" />
|
|
41
|
+
|
|
42
|
+
<Translate value={state.i18n} onChange={fx.changeI18n} />
|
|
43
|
+
|
|
44
|
+
<I18n value="page.name" args={['Sinuhe', 'Maceda', 'Bouchan']} />
|
|
45
|
+
|
|
46
|
+
<button type="button" onClick={(e) => fx.increment(e)}>
|
|
47
|
+
increment
|
|
48
|
+
</button>
|
|
49
|
+
{' '}
|
|
50
|
+
<button type="button" onClick={(e) => fx.decrement(e)}>
|
|
51
|
+
decrement
|
|
52
|
+
</button>
|
|
53
|
+
{' '}
|
|
54
|
+
<button type="button" onClick={() => fx.zero({ value: 0 })}>
|
|
55
|
+
zero
|
|
56
|
+
</button>
|
|
57
|
+
{' '}
|
|
58
|
+
{state.num}
|
|
59
|
+
{' '}
|
|
60
|
+
{state.loading ? <span> Loading... </span> : <span> View.. </span>}
|
|
61
|
+
</header>
|
|
62
|
+
|
|
63
|
+
<aside className="m-2">
|
|
64
|
+
<Link href="/" className="mr-2">
|
|
65
|
+
/
|
|
66
|
+
</Link>
|
|
67
|
+
<Link href="#/" className="mr-2">
|
|
68
|
+
/home
|
|
69
|
+
</Link>
|
|
70
|
+
<Link href="#/env" className="mr-2">
|
|
71
|
+
/env
|
|
72
|
+
</Link>
|
|
73
|
+
<Link href="#/my-context" className="mr-2">
|
|
74
|
+
/my-context
|
|
75
|
+
</Link>
|
|
76
|
+
<Link href="#/mockapi" className="mr-2">
|
|
77
|
+
/mockapi
|
|
78
|
+
</Link>
|
|
79
|
+
<Link
|
|
80
|
+
href="#/search-params"
|
|
81
|
+
value={{ id: 1, user: 'Sinuhe' }}
|
|
82
|
+
className="mr-2"
|
|
83
|
+
>
|
|
84
|
+
/search-params
|
|
85
|
+
</Link>
|
|
86
|
+
<Link href="#/subpage/hello" className="mr-2">
|
|
87
|
+
/subpage/hello
|
|
88
|
+
</Link>
|
|
89
|
+
<Link href="#/translate" className="mr-2">
|
|
90
|
+
/translate
|
|
91
|
+
</Link>
|
|
92
|
+
<Link href="#/counter" className="mr-2">
|
|
93
|
+
/counter
|
|
94
|
+
</Link>
|
|
95
|
+
<Link href="#/images" className="mr-2">
|
|
96
|
+
/images
|
|
97
|
+
</Link>
|
|
98
|
+
<Link href="#/icons" className="mr-2">
|
|
99
|
+
/icons
|
|
100
|
+
</Link>
|
|
101
|
+
<Link href="#/resize" className="mr-2">
|
|
102
|
+
/resize
|
|
103
|
+
</Link>
|
|
104
|
+
<Link href="#/no" className="mr-2">
|
|
105
|
+
/no
|
|
106
|
+
</Link>
|
|
107
|
+
</aside>
|
|
108
|
+
|
|
109
|
+
<main ref={ref} className="m-2">
|
|
110
|
+
{Page && <Page qs={qs.queryString} resize={resize} />}
|
|
111
|
+
</main>
|
|
112
|
+
</PagesContext>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createUser, deleteUser, getUser, updateUser } from 'services/api'
|
|
2
|
+
|
|
3
|
+
const initialState = {
|
|
4
|
+
users: {},
|
|
5
|
+
user: {},
|
|
6
|
+
form: {
|
|
7
|
+
id: 0,
|
|
8
|
+
name: ''
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function handlerUser({ payload, set }) {
|
|
13
|
+
try {
|
|
14
|
+
const { data } = await getUser({ path: { id: payload } })
|
|
15
|
+
set({ users: data, user: {} })
|
|
16
|
+
} catch (e) {
|
|
17
|
+
console.error(e)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function handlerCreateUser({ state, set }) {
|
|
22
|
+
try {
|
|
23
|
+
const { data } = await createUser({
|
|
24
|
+
body: {
|
|
25
|
+
username: state.form.name,
|
|
26
|
+
profile: {
|
|
27
|
+
firstName: state.form.name,
|
|
28
|
+
lastName: state.form.name
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
set({ users: {}, user: data })
|
|
33
|
+
} catch (e) {
|
|
34
|
+
console.error(e)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function handlerUpdateUser({ payload, state, set }) {
|
|
39
|
+
try {
|
|
40
|
+
const { data } = await updateUser({
|
|
41
|
+
path: { id: payload },
|
|
42
|
+
body: {
|
|
43
|
+
username: state.form.name,
|
|
44
|
+
profile: {
|
|
45
|
+
firstName: state.form.name,
|
|
46
|
+
lastName: state.form.name
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
set({ users: {}, user: data })
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.error(e)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function handlerDeleteUser({ payload }) {
|
|
57
|
+
try {
|
|
58
|
+
const { data } = await deleteUser({ path: { id: payload } })
|
|
59
|
+
console.info(data)
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error(e)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default {
|
|
66
|
+
initialState,
|
|
67
|
+
handlerUser,
|
|
68
|
+
handlerCreateUser,
|
|
69
|
+
handlerUpdateUser,
|
|
70
|
+
handlerDeleteUser
|
|
71
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { css, useFx } from 'nextia'
|
|
2
|
+
import functions from './functions'
|
|
3
|
+
import './style.css'
|
|
4
|
+
|
|
5
|
+
export default function MockapiPage() {
|
|
6
|
+
const { initialState, state, fx } = useFx(functions)
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<section className={css('MockapiPage', 'container')}>
|
|
10
|
+
<div>
|
|
11
|
+
<button type="button" onClick={() => fx.reset(['users', 'user'])}>
|
|
12
|
+
Reset
|
|
13
|
+
</button>
|
|
14
|
+
|
|
15
|
+
<button
|
|
16
|
+
type="button"
|
|
17
|
+
onClick={() => {
|
|
18
|
+
fx.reset(['users', 'user'])
|
|
19
|
+
fx.handlerUser()
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
Get users
|
|
23
|
+
</button>
|
|
24
|
+
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
onClick={() => {
|
|
28
|
+
fx.reset(['users', 'user'])
|
|
29
|
+
fx.handlerUser(state.form.id)
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
Get user
|
|
33
|
+
</button>
|
|
34
|
+
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
onClick={() => {
|
|
38
|
+
fx.reset(['users', 'user'])
|
|
39
|
+
fx.handlerCreateUser()
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
42
|
+
Create user
|
|
43
|
+
</button>
|
|
44
|
+
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
onClick={() => {
|
|
48
|
+
fx.reset(['users', 'user'])
|
|
49
|
+
fx.handlerUpdateUser(state.form.id)
|
|
50
|
+
}}
|
|
51
|
+
>
|
|
52
|
+
Update user
|
|
53
|
+
</button>
|
|
54
|
+
|
|
55
|
+
<button
|
|
56
|
+
type="button"
|
|
57
|
+
onClick={() => {
|
|
58
|
+
fx.reset(['users', 'user'])
|
|
59
|
+
fx.handlerDeleteUser(state.form.id)
|
|
60
|
+
}}
|
|
61
|
+
>
|
|
62
|
+
Delete user
|
|
63
|
+
</button>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div>
|
|
67
|
+
<h1>MockapiPage</h1>
|
|
68
|
+
|
|
69
|
+
<div>
|
|
70
|
+
id:{' '}
|
|
71
|
+
<input
|
|
72
|
+
type="text"
|
|
73
|
+
name="form.id"
|
|
74
|
+
value={state.form.id}
|
|
75
|
+
onChange={(evt) => fx.change(evt)}
|
|
76
|
+
/>
|
|
77
|
+
</div>
|
|
78
|
+
<div>
|
|
79
|
+
name:{' '}
|
|
80
|
+
<input
|
|
81
|
+
type="text"
|
|
82
|
+
name="form.name"
|
|
83
|
+
value={state.form.name}
|
|
84
|
+
onChange={(evt) => fx.change(evt)}
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<section>
|
|
90
|
+
<article style={{ display: 'flex' }}>
|
|
91
|
+
<pre style={{ margin: '0 50px 0 50px', width: '250px' }}>
|
|
92
|
+
state = {JSON.stringify(state, undefined, 2)}
|
|
93
|
+
</pre>
|
|
94
|
+
<pre style={{ margin: '0 5px 0 5px', width: '250px' }}>
|
|
95
|
+
initialState = {JSON.stringify(initialState, undefined, 2)}
|
|
96
|
+
</pre>
|
|
97
|
+
</article>
|
|
98
|
+
</section>
|
|
99
|
+
</section>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.MockapiPage {
|
|
2
|
+
background-color: #21252b;
|
|
3
|
+
|
|
4
|
+
&.container {
|
|
5
|
+
display: flex;
|
|
6
|
+
gap: 20px;
|
|
7
|
+
padding: 20px;
|
|
8
|
+
|
|
9
|
+
div {
|
|
10
|
+
width: 300px;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
p {
|
|
15
|
+
padding-left: 25px;
|
|
16
|
+
margin: 0px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
pre {
|
|
20
|
+
color: gray;
|
|
21
|
+
font-size: 12px;
|
|
22
|
+
max-height: 700px;
|
|
23
|
+
overflow: auto;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
button {
|
|
27
|
+
margin: 10px;
|
|
28
|
+
height: 50px;
|
|
29
|
+
width: 180px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
input[type="text"] {
|
|
33
|
+
margin: 20px;
|
|
34
|
+
height: 30px;
|
|
35
|
+
width: 180px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
input[type="checkbox"] {
|
|
39
|
+
height: 30px;
|
|
40
|
+
width: 30px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
input[type="radio"] {
|
|
44
|
+
height: 30px;
|
|
45
|
+
width: 30px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
select {
|
|
49
|
+
margin-left: 40px;
|
|
50
|
+
height: 30px;
|
|
51
|
+
width: 180px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.my-css {
|
|
55
|
+
font-size: 20px;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { css, useFx } from 'nextia'
|
|
2
|
+
import { useEffect } from 'react'
|
|
3
|
+
import functions from './functions'
|
|
4
|
+
import './style.css'
|
|
5
|
+
|
|
6
|
+
export default function MyContext() {
|
|
7
|
+
const { state, fx, context } = useFx(functions)
|
|
8
|
+
|
|
9
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: fx is stable and init should only run once
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
fx.init()
|
|
12
|
+
}, [])
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section className={css('MyContext', '')}>
|
|
16
|
+
<br />
|
|
17
|
+
<button type="button" onClick={(e) => context.fx.increment(e)}>
|
|
18
|
+
increment
|
|
19
|
+
</button>
|
|
20
|
+
{' '}
|
|
21
|
+
<button type="button" onClick={(e) => context.fx.decrement(e)}>
|
|
22
|
+
decrement
|
|
23
|
+
</button>
|
|
24
|
+
{' '}
|
|
25
|
+
<button type="button" onClick={() => context.fx.zero({ value: 0 })}>
|
|
26
|
+
zero
|
|
27
|
+
</button>
|
|
28
|
+
{' '}
|
|
29
|
+
{context.state.num}
|
|
30
|
+
</section>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { css, useFx } from 'nextia'
|
|
2
|
+
import functions from './functions'
|
|
3
|
+
import './style.css'
|
|
4
|
+
|
|
5
|
+
export default function ResizePage({ resize }) {
|
|
6
|
+
const { state, fx } = useFx(functions)
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<section className={css('ResizePage', '')}>
|
|
10
|
+
<pre style={{ margin: '0 50px 0 50px', width: '250px' }}>
|
|
11
|
+
{JSON.stringify(resize, undefined, 2)}
|
|
12
|
+
</pre>
|
|
13
|
+
</section>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Link } from 'components'
|
|
2
|
+
import { css, useFx } from 'nextia'
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
|
+
import functions from './functions'
|
|
5
|
+
import './style.css'
|
|
6
|
+
|
|
7
|
+
export default function SearchParamsPage({ qs }) {
|
|
8
|
+
const { state, fx } = useFx(functions)
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
console.info(qs)
|
|
12
|
+
}, [qs])
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section className={css('SearchParamsPage', '')}>
|
|
16
|
+
<br />
|
|
17
|
+
|
|
18
|
+
<Link href="/">Go to href=/</Link>
|
|
19
|
+
|
|
20
|
+
<br />
|
|
21
|
+
|
|
22
|
+
<Link value={{ id: 2, user: 'Maceda' }}>Link id=2 user=Maceda </Link>
|
|
23
|
+
|
|
24
|
+
<br />
|
|
25
|
+
|
|
26
|
+
<Link value={{ id: 1, user: 'Sinuhe' }}>Link id=1 user=Sinuhe</Link>
|
|
27
|
+
|
|
28
|
+
<br />
|
|
29
|
+
<br />
|
|
30
|
+
|
|
31
|
+
<pre style={{ margin: '0 50px 0 50px' }}>
|
|
32
|
+
{JSON.stringify(qs, undefined, 2)}
|
|
33
|
+
</pre>
|
|
34
|
+
</section>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { css, useFx } from 'nextia'
|
|
2
|
+
import functions from './functions'
|
|
3
|
+
import './style.css'
|
|
4
|
+
|
|
5
|
+
export default function SubpageHelloPage() {
|
|
6
|
+
const { state, fx } = useFx(functions)
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<section className={css('SubpageHelloPage', '')}>/subpage/hello</section>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { css, useFx } from 'nextia'
|
|
2
|
+
import functions from './functions'
|
|
3
|
+
import './style.css'
|
|
4
|
+
import { I18n, Message } from 'components'
|
|
5
|
+
|
|
6
|
+
export default function TranslatePage() {
|
|
7
|
+
const { state, fx } = useFx(functions)
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<section className={css('TranslatePage', '')}>
|
|
11
|
+
<I18n value="page.name" args={['Sinuhe', 'Maceda', 'Bouchan']} />
|
|
12
|
+
|
|
13
|
+
<ul>
|
|
14
|
+
<li>
|
|
15
|
+
<I18n value="ui.ok" />
|
|
16
|
+
</li>
|
|
17
|
+
<li>
|
|
18
|
+
<I18n value="ui.back" />
|
|
19
|
+
</li>
|
|
20
|
+
<li>
|
|
21
|
+
<I18n value="page.user.family" />
|
|
22
|
+
</li>
|
|
23
|
+
<li>
|
|
24
|
+
<I18n value="page.module.block.docker" />
|
|
25
|
+
</li>
|
|
26
|
+
</ul>
|
|
27
|
+
|
|
28
|
+
<Message />
|
|
29
|
+
</section>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { env } from 'utils'
|
|
2
|
+
import { DELETE, GET, POST, PUT } from './http'
|
|
3
|
+
|
|
4
|
+
const API = env.PUBLIC_API
|
|
5
|
+
|
|
6
|
+
export const getUser = (p) => GET(`${API}/user/:id`, p.path, p.body)
|
|
7
|
+
export const createUser = (p) => POST(`${API}/user`, p.path, p.body)
|
|
8
|
+
export const updateUser = (p) => PUT(`${API}/user/:id`, p.path, p.body)
|
|
9
|
+
export const deleteUser = (p) => DELETE(`${API}/user/:id`, p.path, p.body)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
function urlTemplate(url, path) {
|
|
2
|
+
const params = url.match(/:\w+/g) ?? []
|
|
3
|
+
|
|
4
|
+
return params.reduce((acc, e) => {
|
|
5
|
+
const key = e.split(':')[1]
|
|
6
|
+
return acc.replaceAll(e, path[key] ?? '')
|
|
7
|
+
}, url)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function request(method, url, path, body, headers) {
|
|
11
|
+
url = urlTemplate(url, path)
|
|
12
|
+
|
|
13
|
+
if (method === 'GET') {
|
|
14
|
+
url += Object.keys(body).length ? `?${new URLSearchParams(body)}` : ''
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const response = await fetch(url, {
|
|
18
|
+
method,
|
|
19
|
+
headers: { 'Content-Type': 'application/json', ...headers },
|
|
20
|
+
...(method !== 'GET' && {
|
|
21
|
+
body: JSON.stringify(body)
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const { ok, status, statusText } = response
|
|
26
|
+
|
|
27
|
+
if (ok) return { ok, status, statusText, data: await response.json() }
|
|
28
|
+
|
|
29
|
+
throw new Error(`ok: ${ok} , status: ${status} , statusText: ${statusText}`)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const factory =
|
|
33
|
+
(method) =>
|
|
34
|
+
(url = '', path = {}, body = {}, headers = {}) =>
|
|
35
|
+
request(method, url, path, body, headers)
|
|
36
|
+
|
|
37
|
+
export const GET = factory('GET')
|
|
38
|
+
export const POST = factory('POST')
|
|
39
|
+
export const PUT = factory('PUT')
|
|
40
|
+
export const DELETE = factory('DELETE')
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
view-transition-name: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* fade */
|
|
6
|
+
|
|
7
|
+
@keyframes fade-in {
|
|
8
|
+
from {
|
|
9
|
+
opacity: 0;
|
|
10
|
+
}
|
|
11
|
+
to {
|
|
12
|
+
opacity: 1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
@keyframes fade-out {
|
|
16
|
+
from {
|
|
17
|
+
opacity: 1;
|
|
18
|
+
}
|
|
19
|
+
to {
|
|
20
|
+
opacity: 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
::view-transition-old(fade) {
|
|
25
|
+
animation: fade-out ease 0.3s forwards;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
::view-transition-new(fade) {
|
|
29
|
+
animation: fade-in ease 0.3s forwards;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* count */
|
|
33
|
+
|
|
34
|
+
@keyframes count-in {
|
|
35
|
+
from {
|
|
36
|
+
scale: 1 0;
|
|
37
|
+
}
|
|
38
|
+
to {
|
|
39
|
+
scale: 1 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@keyframes count-out {
|
|
44
|
+
from {
|
|
45
|
+
scale: 1 1;
|
|
46
|
+
}
|
|
47
|
+
to {
|
|
48
|
+
scale: 1 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
::view-transition-new(count) {
|
|
53
|
+
animation: count-in 0.25s forwards;
|
|
54
|
+
transform-origin: 50% 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
::view-transition-old(count) {
|
|
58
|
+
animation: count-out 0.25s forwards;
|
|
59
|
+
transform-origin: 50% 100%;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* count2 */
|
|
63
|
+
|
|
64
|
+
::view-transition-new(count2) {
|
|
65
|
+
animation: count-in 0.25s forwards;
|
|
66
|
+
transform-origin: 10% 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
::view-transition-old(count2) {
|
|
70
|
+
animation: count-out 0.25s forwards;
|
|
71
|
+
transform-origin: 10% 0%;
|
|
72
|
+
}
|
|
Binary file
|