nextia 6.1.1 → 7.0.2

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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/biome.json +21 -0
  3. package/package.json +13 -8
  4. package/src/bin.js +239 -0
  5. package/src/{lib.js → lib/fx.js} +18 -33
  6. package/src/lib/index.js +32 -0
  7. package/src/lib/ui.js +112 -0
  8. package/src/lib/utils.js +107 -0
  9. package/template/README.md +29 -0
  10. package/template/_env.dev +4 -0
  11. package/template/_env.prod +1 -0
  12. package/template/_env.test +1 -0
  13. package/template/_gitignore +10 -0
  14. package/template/biome.json +21 -0
  15. package/template/package.json +35 -0
  16. package/template/public/error.html +14 -0
  17. package/template/public/logo.svg +105 -0
  18. package/template/src/assets/i18n/index.js +26 -0
  19. package/template/src/assets/img/image.svg +6 -0
  20. package/template/src/assets/img/image.webp +0 -0
  21. package/template/src/components/Counter/index.jsx +33 -0
  22. package/template/src/components/Counter/style.css +5 -0
  23. package/template/src/components/Message/index.jsx +12 -0
  24. package/template/src/components/index.js +6 -0
  25. package/template/src/components/ui/Translate/index.jsx +20 -0
  26. package/template/src/index.html +18 -0
  27. package/template/src/index.jsx +4 -0
  28. package/template/src/pages/env/functions.js +3 -0
  29. package/template/src/pages/env/index.jsx +26 -0
  30. package/template/src/pages/env/style.css +2 -0
  31. package/template/src/pages/functions.js +37 -0
  32. package/template/src/pages/home/functions.js +43 -0
  33. package/template/src/pages/home/index.jsx +211 -0
  34. package/template/src/pages/home/style.css +51 -0
  35. package/template/src/pages/http/not-found/index.jsx +10 -0
  36. package/template/src/pages/http/not-found/style.css +2 -0
  37. package/template/src/pages/icons/functions.js +3 -0
  38. package/template/src/pages/icons/index.jsx +21 -0
  39. package/template/src/pages/icons/style.css +8 -0
  40. package/template/src/pages/images/functions.js +3 -0
  41. package/template/src/pages/images/index.jsx +25 -0
  42. package/template/src/pages/images/style.css +27 -0
  43. package/template/src/pages/index.jsx +124 -0
  44. package/template/src/pages/mockapi/functions.js +71 -0
  45. package/template/src/pages/mockapi/index.jsx +101 -0
  46. package/template/src/pages/mockapi/style.css +57 -0
  47. package/template/src/pages/my-context/functions.js +7 -0
  48. package/template/src/pages/my-context/index.jsx +32 -0
  49. package/template/src/pages/my-context/style.css +2 -0
  50. package/template/src/pages/resize/functions.js +3 -0
  51. package/template/src/pages/resize/index.jsx +15 -0
  52. package/template/src/pages/resize/style.css +2 -0
  53. package/template/src/pages/search-params/functions.js +3 -0
  54. package/template/src/pages/search-params/index.jsx +35 -0
  55. package/template/src/pages/search-params/style.css +2 -0
  56. package/template/src/pages/subpage/hello/functions.js +3 -0
  57. package/template/src/pages/subpage/hello/index.jsx +11 -0
  58. package/template/src/pages/subpage/hello/style.css +2 -0
  59. package/template/src/pages/translate/functions.js +5 -0
  60. package/template/src/pages/translate/index.jsx +31 -0
  61. package/template/src/pages/translate/style.css +12 -0
  62. package/template/src/pages/view-transition/functions.js +6 -0
  63. package/template/src/pages/view-transition/index.jsx +30 -0
  64. package/template/src/pages/view-transition/style.css +2 -0
  65. package/template/src/services/api.js +9 -0
  66. package/template/src/services/http.js +40 -0
  67. package/template/src/theme/fonts/Roboto-Regular.ttf +0 -0
  68. package/template/src/theme/fonts/index.css +7 -0
  69. package/template/src/theme/icons/icons.svg +125 -0
  70. package/template/src/theme/icons/index.css +55 -0
  71. package/template/src/theme/index.css +39 -0
  72. package/template/src/theme/utils/index.css +29 -0
  73. package/template/src/theme/utils/view-transition.css +72 -0
  74. package/template/src/utils/index.js +5 -0
  75. package/template/test/index.test.js +11 -0
  76. package/template/vite.config.js +97 -0
@@ -0,0 +1,51 @@
1
+ .HomePage {
2
+ background-color: #21252b;
3
+
4
+ &.container {
5
+ display: flex;
6
+ }
7
+
8
+ p {
9
+ padding-left: 25px;
10
+ margin: 0px;
11
+ }
12
+
13
+ pre {
14
+ color: gray;
15
+ font-size: 12px;
16
+ max-height: 700px;
17
+ overflow: auto;
18
+ }
19
+
20
+ button {
21
+ margin: 12px;
22
+ height: 50px;
23
+ width: 200px;
24
+ }
25
+
26
+ input[type="text"] {
27
+ margin: 20px;
28
+ height: 30px;
29
+ width: 180px;
30
+ }
31
+
32
+ input[type="checkbox"] {
33
+ height: 30px;
34
+ width: 30px;
35
+ }
36
+
37
+ input[type="radio"] {
38
+ height: 30px;
39
+ width: 30px;
40
+ }
41
+
42
+ select {
43
+ margin-left: 40px;
44
+ height: 30px;
45
+ width: 180px;
46
+ }
47
+
48
+ .my-css {
49
+ font-size: 20px;
50
+ }
51
+ }
@@ -0,0 +1,10 @@
1
+ import { css } from 'nextia'
2
+ import './style.css'
3
+
4
+ export default function HttpNotFoundPage() {
5
+ return (
6
+ <section className={css('HttpNotFoundPage')}>
7
+ <h5>Not Found</h5>
8
+ </section>
9
+ )
10
+ }
@@ -0,0 +1,2 @@
1
+ .HttpNotFoundPage {
2
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -0,0 +1,21 @@
1
+ import { css, Icon, useFx } from 'nextia'
2
+ import functions from './functions'
3
+ import './style.css'
4
+
5
+ export default function IconsPage() {
6
+ const { state, fx } = useFx(functions)
7
+
8
+ return (
9
+ <section className={css('IconsPage', '')}>
10
+ <article>
11
+ <Icon id="globe" width="32" />
12
+ <Icon id="camera" width="32" />
13
+ <Icon id="video" width="32" />
14
+ </article>
15
+
16
+ <article>
17
+ <Icon id="exit" animate width="32" />
18
+ </article>
19
+ </section>
20
+ )
21
+ }
@@ -0,0 +1,8 @@
1
+ .IconsPage {
2
+ display: flex;
3
+ justify-content: space-around;
4
+
5
+ svg {
6
+ margin-right: 10px;
7
+ }
8
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -0,0 +1,25 @@
1
+ import image from 'assets/img/image.webp'
2
+ import { css, Svg, useFx } from 'nextia'
3
+ import functions from './functions'
4
+ import './style.css'
5
+ import imageSvg from 'assets/img/image.svg?raw'
6
+
7
+ export default function ImagesPage() {
8
+ const { state, fx } = useFx(functions)
9
+
10
+ return (
11
+ <section className={css('ImagesPage', '')}>
12
+ <p>css-img</p>
13
+ <div className="css-img" />
14
+
15
+ <p>img</p>
16
+ <img src={image} alt="img" width="64" />
17
+
18
+ <p>svg</p>
19
+ <Svg src={imageSvg} width="64" />
20
+
21
+ <p>svg+css</p>
22
+ <Svg className="svg-css" src={imageSvg} width="64" />
23
+ </section>
24
+ )
25
+ }
@@ -0,0 +1,27 @@
1
+ .ImagesPage {
2
+ margin-left: 50px;
3
+
4
+ .css-img {
5
+ background: url("assets/img/image.webp") no-repeat;
6
+ height: 64px;
7
+ background-repeat: no-repeat;
8
+ background-size: contain;
9
+ }
10
+
11
+ .svg-css {
12
+ #label {
13
+ animation: svg-css_arrow 2s ease-in-out infinite;
14
+ }
15
+ }
16
+ }
17
+
18
+ @keyframes svg-css_arrow {
19
+ 0%,
20
+ 100% {
21
+ transform: translateY(-2px);
22
+ }
23
+
24
+ 50% {
25
+ transform: translateY(2px);
26
+ }
27
+ }
@@ -0,0 +1,124 @@
1
+ import i18nFile from 'assets/i18n'
2
+ import { Translate } from 'components'
3
+ import {
4
+ I18n,
5
+ Icon,
6
+ Link,
7
+ PagesFx,
8
+ startViewTransition,
9
+ useFx,
10
+ useQueryString,
11
+ useResize
12
+ } from 'nextia'
13
+ import { lazy, useEffect, useRef, useState } from 'react'
14
+ import iconsFile from 'theme/icons/icons.svg?raw'
15
+ import functions from './functions.js'
16
+
17
+ export default function Pages() {
18
+ const pages = useFx(functions)
19
+ const { state, fx } = pages
20
+
21
+ const [Page, setPage] = useState()
22
+ const qs = useQueryString()
23
+ const resize = useResize()
24
+ const ref = useRef()
25
+
26
+ useEffect(() => {
27
+ const hash = ['', '#/'].includes(qs.hash) ? '#/home' : qs.hash
28
+
29
+ const page = lazy(async () => {
30
+ const path = hash.substring(2).split('/')
31
+
32
+ try {
33
+ if (path.length === 1) {
34
+ return await import(`./${path[0]}/index.jsx`)
35
+ } else if (path.length === 2) {
36
+ return await import(`./${path[0]}/${path[1]}/index.jsx`)
37
+ }
38
+ } catch (e) {
39
+ console.error(e)
40
+ return await import('./http/not-found/index.jsx')
41
+ }
42
+ })
43
+
44
+ startViewTransition(setPage(page), ref.current)
45
+ }, [qs.hash])
46
+
47
+ return (
48
+ <PagesFx value={{ context: pages, icons: iconsFile, i18n: i18nFile }}>
49
+ <header style={{ display: 'flex', gap: '20px' }}>
50
+ <Icon id="globe" width="24" />
51
+
52
+ <Translate />
53
+
54
+ <I18n value="page.name" args={['Sinuhe', 'Maceda', 'Bouchan']} />
55
+
56
+ <button type="button" onClick={(e) => fx.increment(e)}>
57
+ increment
58
+ </button>
59
+ {' '}
60
+ <button type="button" onClick={(e) => fx.decrement(e)}>
61
+ decrement
62
+ </button>
63
+ {' '}
64
+ <button type="button" onClick={() => fx.zero({ value: 0 })}>
65
+ zero
66
+ </button>
67
+ {' '}
68
+ {state.num}
69
+ {' '}
70
+ {state.loading ? <span> Loading... </span> : <span> View.. </span>}
71
+ </header>
72
+
73
+ <aside className="m-2">
74
+ <Link href="/" className="mr-2">
75
+ /
76
+ </Link>
77
+ <Link href="#/" className="mr-2">
78
+ /home
79
+ </Link>
80
+ <Link href="#/env" className="mr-2">
81
+ /env
82
+ </Link>
83
+ <Link href="#/my-context" className="mr-2">
84
+ /my-context
85
+ </Link>
86
+ <Link href="#/mockapi" className="mr-2">
87
+ /mockapi
88
+ </Link>
89
+ <Link
90
+ href="#/search-params"
91
+ value={{ id: 1, user: 'Sinuhe' }}
92
+ className="mr-2"
93
+ >
94
+ /search-params
95
+ </Link>
96
+ <Link href="#/subpage/hello" className="mr-2">
97
+ /subpage/hello
98
+ </Link>
99
+ <Link href="#/translate" className="mr-2">
100
+ /translate
101
+ </Link>
102
+ <Link href="#/view-transition" className="mr-2">
103
+ /view-transition
104
+ </Link>
105
+ <Link href="#/images" className="mr-2">
106
+ /images
107
+ </Link>
108
+ <Link href="#/icons" className="mr-2">
109
+ /icons
110
+ </Link>
111
+ <Link href="#/resize" className="mr-2">
112
+ /resize
113
+ </Link>
114
+ <Link href="#/dashboard" className="mr-2">
115
+ /not-found
116
+ </Link>
117
+ </aside>
118
+
119
+ <main ref={ref} className="m-2">
120
+ {Page && <Page qs={qs.queryString} resize={resize} />}
121
+ </main>
122
+ </PagesFx>
123
+ )
124
+ }
@@ -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,7 @@
1
+ const initialState = {}
2
+
3
+ function init({ context }) {
4
+ context.fx.set({ num: 300 })
5
+ }
6
+
7
+ export default { initialState, init }
@@ -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,2 @@
1
+ .MyContext {
2
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -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,2 @@
1
+ .ResizePage {
2
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -0,0 +1,35 @@
1
+ import { css, Link, useFx } from 'nextia'
2
+ import { useEffect } from 'react'
3
+ import functions from './functions'
4
+ import './style.css'
5
+
6
+ export default function SearchParamsPage({ qs }) {
7
+ const { state, fx } = useFx(functions)
8
+
9
+ useEffect(() => {
10
+ console.info(qs)
11
+ }, [qs])
12
+
13
+ return (
14
+ <section className={css('SearchParamsPage', '')}>
15
+ <br />
16
+
17
+ <Link href="/">Go to href=/</Link>
18
+
19
+ <br />
20
+
21
+ <Link value={{ id: 2, user: 'Maceda' }}>Link id=2 user=Maceda </Link>
22
+
23
+ <br />
24
+
25
+ <Link value={{ id: 1, user: 'Sinuhe' }}>Link id=1 user=Sinuhe</Link>
26
+
27
+ <br />
28
+ <br />
29
+
30
+ <pre style={{ margin: '0 50px 0 50px' }}>
31
+ {JSON.stringify(qs, undefined, 2)}
32
+ </pre>
33
+ </section>
34
+ )
35
+ }
@@ -0,0 +1,2 @@
1
+ .SearchParamsPage {
2
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -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,2 @@
1
+ .SubpageHelloPage {
2
+ }
@@ -0,0 +1,5 @@
1
+ const initialState = {}
2
+
3
+ export default {
4
+ initialState
5
+ }