nextia 6.0.4 → 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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/biome.json +21 -0
  3. package/package.json +14 -6
  4. package/src/bin.js +240 -0
  5. package/src/lib.js +21 -29
  6. package/template/README.md +29 -0
  7. package/template/_env.dev +4 -0
  8. package/template/_env.prod +1 -0
  9. package/template/_env.test +1 -0
  10. package/template/_gitignore +10 -0
  11. package/template/package.json +35 -0
  12. package/template/public/error.html +14 -0
  13. package/template/public/logo.svg +105 -0
  14. package/template/src/assets/i18n/index.js +26 -0
  15. package/template/src/assets/img/image.jpg +0 -0
  16. package/template/src/components/Counter/index.jsx +34 -0
  17. package/template/src/components/Counter/style.css +5 -0
  18. package/template/src/components/Message/index.jsx +12 -0
  19. package/template/src/components/index.js +10 -0
  20. package/template/src/components/ui/I18n/index.jsx +23 -0
  21. package/template/src/components/ui/Icon/index.jsx +50 -0
  22. package/template/src/components/ui/Link/index.jsx +12 -0
  23. package/template/src/components/ui/Svg/index.jsx +54 -0
  24. package/template/src/components/ui/Translate/index.jsx +18 -0
  25. package/template/src/index.html +18 -0
  26. package/template/src/index.jsx +4 -0
  27. package/template/src/pages/counter/functions.js +6 -0
  28. package/template/src/pages/counter/index.jsx +51 -0
  29. package/template/src/pages/counter/style.css +2 -0
  30. package/template/src/pages/env/functions.js +3 -0
  31. package/template/src/pages/env/index.jsx +27 -0
  32. package/template/src/pages/env/style.css +2 -0
  33. package/template/src/pages/functions.js +37 -0
  34. package/template/src/pages/home/functions.js +43 -0
  35. package/template/src/pages/home/index.jsx +211 -0
  36. package/template/src/pages/home/style.css +51 -0
  37. package/template/src/pages/http/not-found/index.jsx +10 -0
  38. package/template/src/pages/http/not-found/style.css +2 -0
  39. package/template/src/pages/icons/functions.js +3 -0
  40. package/template/src/pages/icons/index.jsx +20 -0
  41. package/template/src/pages/icons/style.css +5 -0
  42. package/template/src/pages/images/functions.js +3 -0
  43. package/template/src/pages/images/index.jsx +20 -0
  44. package/template/src/pages/images/style.css +8 -0
  45. package/template/src/pages/index.jsx +114 -0
  46. package/template/src/pages/mockapi/functions.js +71 -0
  47. package/template/src/pages/mockapi/index.jsx +101 -0
  48. package/template/src/pages/mockapi/style.css +57 -0
  49. package/template/src/pages/my-context/functions.js +7 -0
  50. package/template/src/pages/my-context/index.jsx +32 -0
  51. package/template/src/pages/my-context/style.css +2 -0
  52. package/template/src/pages/resize/functions.js +3 -0
  53. package/template/src/pages/resize/index.jsx +15 -0
  54. package/template/src/pages/resize/style.css +2 -0
  55. package/template/src/pages/search-params/functions.js +3 -0
  56. package/template/src/pages/search-params/index.jsx +36 -0
  57. package/template/src/pages/search-params/style.css +2 -0
  58. package/template/src/pages/subpage/hello/functions.js +3 -0
  59. package/template/src/pages/subpage/hello/index.jsx +11 -0
  60. package/template/src/pages/subpage/hello/style.css +2 -0
  61. package/template/src/pages/translate/functions.js +5 -0
  62. package/template/src/pages/translate/index.jsx +31 -0
  63. package/template/src/pages/translate/style.css +12 -0
  64. package/template/src/services/api.js +9 -0
  65. package/template/src/services/http.js +40 -0
  66. package/template/src/theme/animations.css +72 -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/exit.svg +69 -0
  70. package/template/src/theme/icons/icons.svg +126 -0
  71. package/template/src/theme/index.css +39 -0
  72. package/template/src/theme/util.css +27 -0
  73. package/template/src/utils/hooks.js +49 -0
  74. package/template/src/utils/index.js +19 -0
  75. package/template/test/index.test.js +12 -0
  76. package/template/vite.config.js +97 -0
@@ -0,0 +1,34 @@
1
+ import { useRef } from 'react'
2
+ import './style.css'
3
+ import { css } from 'nextia'
4
+ import { startViewTransition } from 'utils'
5
+
6
+ export default function Counter({
7
+ name,
8
+ value,
9
+ className,
10
+ style,
11
+ animation = 'count',
12
+ onChange
13
+ }) {
14
+ const ref = useRef()
15
+
16
+ return (
17
+ <article
18
+ className={css('Counter-component', className)}
19
+ style={style}
20
+ name={name}
21
+ >
22
+ <button
23
+ type="button"
24
+ onClick={(e) => {
25
+ startViewTransition(onChange(e), ref.current, animation)
26
+ }}
27
+ >
28
+ Increment
29
+ </button>
30
+
31
+ <span ref={ref}>{value}</span>
32
+ </article>
33
+ )
34
+ }
@@ -0,0 +1,5 @@
1
+ .Counter-component {
2
+ span {
3
+ font-size: 60px;
4
+ }
5
+ }
@@ -0,0 +1,12 @@
1
+ import { I18n } from 'components'
2
+
3
+ export default function Messages({ name, className, style }) {
4
+ return (
5
+ <article className={className} style={style} name={name}>
6
+ Message-component :{' '}
7
+ <span>
8
+ <I18n value="page.user.family" />
9
+ </span>
10
+ </article>
11
+ )
12
+ }
@@ -0,0 +1,10 @@
1
+ import Counter from './Counter'
2
+ import Message from './Message'
3
+ // ui
4
+ import I18n from './ui/I18n'
5
+ import Icon from './ui/Icon'
6
+ import Link from './ui/Link'
7
+ import Svg from './ui/Svg'
8
+ import Translate from './ui/Translate'
9
+
10
+ export { Counter, I18n, Icon, Link, Message, Svg, Translate }
@@ -0,0 +1,23 @@
1
+ import i18nFile from 'assets/i18n'
2
+ import { useFx } from 'nextia'
3
+
4
+ export default function UiI18n({ value, args = [] }) {
5
+ const { context } = useFx()
6
+
7
+ try {
8
+ let text = value.split('.').reduce((ac, el) => ac[el], i18nFile)
9
+ text = text[i18nFile.locales.indexOf(context.state.i18n.currentLocale)]
10
+
11
+ if (args) {
12
+ text = text.replace(
13
+ /([{}])\\1|[{](.*?)(?:!(.+?))?[}]/g,
14
+ (match, _literal, number) => args[number] || match
15
+ )
16
+ }
17
+
18
+ return text
19
+ } catch {
20
+ console.error(`Error in [il8n] => ${value}`)
21
+ return value
22
+ }
23
+ }
@@ -0,0 +1,50 @@
1
+ import { useEffect, useRef } from 'react'
2
+ import icons from 'theme/icons/icons.svg?raw'
3
+
4
+ export default function UiIcon({
5
+ id,
6
+ className,
7
+ style,
8
+ width = '48',
9
+ height,
10
+ viewBox = '0 0 48 48',
11
+ fill = 'none',
12
+ color = 'currentColor',
13
+ stroke = 'currentColor',
14
+ strokeWidth = '2',
15
+ strokeLinecap = 'round',
16
+ strokeLinejoin = 'round',
17
+ ...props
18
+ }) {
19
+ const ref = useRef()
20
+
21
+ useEffect(() => {
22
+ const svg = new DOMParser()
23
+ .parseFromString(icons, 'image/svg+xml')
24
+ .documentElement.getElementById(id)
25
+
26
+ if (svg) {
27
+ ref.current.innerHTML = svg.innerHTML
28
+ }
29
+ }, [id])
30
+
31
+ return (
32
+ <svg
33
+ xmlns="http://www.w3.org/2000/svg"
34
+ ref={ref}
35
+ id={id}
36
+ className={className}
37
+ style={style}
38
+ width={width}
39
+ height={height}
40
+ viewBox={viewBox}
41
+ fill={fill}
42
+ color={color}
43
+ stroke={stroke}
44
+ strokeWidth={strokeWidth}
45
+ strokeLinecap={strokeLinecap}
46
+ strokeLinejoin={strokeLinejoin}
47
+ {...props}
48
+ />
49
+ )
50
+ }
@@ -0,0 +1,12 @@
1
+ export default function UiLink({ children, href, value = {}, ...props }) {
2
+ href ??= window.location.hash.split('?')[0]
3
+ value = Object.keys(value).length
4
+ ? `?${new URLSearchParams(value).toString()}`
5
+ : ''
6
+
7
+ return (
8
+ <a href={href + value} {...props}>
9
+ {children}
10
+ </a>
11
+ )
12
+ }
@@ -0,0 +1,54 @@
1
+ import { useEffect, useRef } from 'react'
2
+
3
+ export default function UiSvg({
4
+ src,
5
+ width = '48',
6
+ height,
7
+ viewBox = '0 0 48 48',
8
+ fill = 'none',
9
+ color = 'currentColor',
10
+ stroke = 'currentColor',
11
+ strokeWidth = '2',
12
+ strokeLinecap = 'round',
13
+ strokeLinejoin = 'round'
14
+ }) {
15
+ const ref = useRef()
16
+
17
+ useEffect(() => {
18
+ if (!ref.current) return
19
+
20
+ const svg = new DOMParser()
21
+ .parseFromString(src, 'image/svg+xml')
22
+ .querySelector('svg')
23
+
24
+ svg.setAttribute('width', width)
25
+ svg.setAttribute('height', height ?? width)
26
+ svg.setAttribute('viewBox', viewBox)
27
+ svg.setAttribute('fill', fill)
28
+ svg.setAttribute('color', color)
29
+ svg.setAttribute('stroke', stroke)
30
+ svg.setAttribute('stroke-width', strokeWidth)
31
+ svg.setAttribute('stroke-linecap', strokeLinecap)
32
+ svg.setAttribute('stroke-linejoin', strokeLinejoin)
33
+
34
+ const shadow =
35
+ ref.current.shadowRoot ?? ref.current.attachShadow({ mode: 'open' })
36
+ shadow.innerHTML = svg.outerHTML
37
+
38
+ ref.current.style.width = `${width}px`
39
+ ref.current.style.height = `${height ?? width}px`
40
+ }, [
41
+ src,
42
+ width,
43
+ height,
44
+ viewBox,
45
+ fill,
46
+ color,
47
+ stroke,
48
+ strokeWidth,
49
+ strokeLinecap,
50
+ strokeLinejoin
51
+ ])
52
+
53
+ return <div ref={ref} />
54
+ }
@@ -0,0 +1,18 @@
1
+ export default function UiTranslate({
2
+ value,
3
+ onChange = () => {},
4
+ className,
5
+ style
6
+ }) {
7
+ return (
8
+ <article className={className} style={style}>
9
+ <select value={value.currentLocale} onChange={onChange}>
10
+ {value.locales.map((e) => (
11
+ <option key={e} value={e} className="m-2">
12
+ {e}
13
+ </option>
14
+ ))}
15
+ </select>
16
+ </article>
17
+ )
18
+ }
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <title>%PUBLIC_TITLE%</title>
7
+ <link rel="shortcut icon" href="logo.svg" />
8
+ <meta name="version" content="%VERSION%" />
9
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
10
+ <link rel="stylesheet" href="theme/index.css" />
11
+ <script type="module" src="index.jsx"></script>
12
+ </head>
13
+
14
+ <body>
15
+ <div id="root"></div>
16
+ </body>
17
+
18
+ </html>
@@ -0,0 +1,4 @@
1
+ import { createRoot } from 'react-dom/client'
2
+ import Pages from './pages'
3
+
4
+ createRoot(document.getElementById('root')).render(<Pages />)
@@ -0,0 +1,6 @@
1
+ const initialState = {
2
+ count: 1,
3
+ count2: 1
4
+ }
5
+
6
+ export default { initialState }
@@ -0,0 +1,51 @@
1
+ import { Counter } from 'components'
2
+ import { css, useFx } from 'nextia'
3
+ import functions from './functions'
4
+ import './style.css'
5
+
6
+ export default function CounterPage() {
7
+ const { state, fx } = useFx(functions)
8
+
9
+ return (
10
+ <section
11
+ className={css(
12
+ 'CounterPage',
13
+ '',
14
+ 'class-test',
15
+ 'class-test',
16
+ {},
17
+ null,
18
+ true,
19
+ false,
20
+ [],
21
+ { 'css-false': false },
22
+ undefined,
23
+ { 'css-true': true },
24
+ { 'css-true': true }
25
+ )}
26
+ >
27
+ Counters
28
+ <div className={css(null)} />
29
+ <div className={css(undefined)} />
30
+ <div className={css([])} />
31
+ <div className={css({})} />
32
+ <div className={css()} />
33
+ <Counter
34
+ value={state.count}
35
+ animation="count"
36
+ onChange={() => {
37
+ fx.set({ count: state.count + 1 })
38
+ }}
39
+ />
40
+ <br />
41
+ <br />
42
+ <Counter
43
+ value={state.count2}
44
+ animation="count2"
45
+ onChange={() => {
46
+ fx.set({ count2: state.count2 + 10 })
47
+ }}
48
+ />
49
+ </section>
50
+ )
51
+ }
@@ -0,0 +1,2 @@
1
+ .CounterPage {
2
+ }
@@ -0,0 +1,3 @@
1
+ const initialState = {}
2
+
3
+ export default { initialState }
@@ -0,0 +1,27 @@
1
+ import { css, useFx } from 'nextia'
2
+ import { useEffect } from 'react'
3
+ import { env } from 'utils'
4
+ import functions from './functions'
5
+ import './style.css'
6
+
7
+ export default function EnvPage() {
8
+ const { state, fx } = useFx(functions)
9
+
10
+ // env
11
+ useEffect(() => {
12
+ console.log('env:', env)
13
+ }, [])
14
+
15
+ return (
16
+ <section className={css('EnvPage', '')}>
17
+ <br />
18
+ <br />
19
+
20
+ <div style={{ display: 'flex' }}>
21
+ <pre style={{ margin: '0 50px 0 50px' }}>
22
+ env = {JSON.stringify(env, undefined, 2)}
23
+ </pre>
24
+ </div>
25
+ </section>
26
+ )
27
+ }
@@ -0,0 +1,2 @@
1
+ .EnvPage {
2
+ }
@@ -0,0 +1,37 @@
1
+ import i18nFile from 'assets/i18n'
2
+
3
+ const initialState = {
4
+ i18n: {
5
+ currentLocale:
6
+ window.localStorage.getItem('i18n') || i18nFile.defaultLocale,
7
+ locales: i18nFile.locales
8
+ },
9
+ loading: false,
10
+ num: 0
11
+ }
12
+
13
+ function changeI18n({ payload, set }) {
14
+ const { value } = payload.target
15
+ set({ i18n: { currentLocale: value } })
16
+ window.localStorage.setItem('i18n', value)
17
+ }
18
+
19
+ function increment({ state, set }) {
20
+ set({ num: state.num + 1 })
21
+ }
22
+
23
+ function decrement({ state, set }) {
24
+ set({ num: state.num - 1 })
25
+ }
26
+
27
+ function zero({ payload, set }) {
28
+ set({ num: payload.value })
29
+ }
30
+
31
+ export default {
32
+ initialState,
33
+ changeI18n,
34
+ increment,
35
+ decrement,
36
+ zero
37
+ }
@@ -0,0 +1,43 @@
1
+ const initialState = {
2
+ channel: 7,
3
+ msg: 'https://sinuhe.dev',
4
+ data: { user: 'Sinuhe MB' },
5
+ myArray: ['A', 'B', 'C'],
6
+ setNameValue: 'name value',
7
+ form: {
8
+ funny: false,
9
+ gender: 'M',
10
+ name: {
11
+ firstName: 'Sinuhe',
12
+ lastName: 'Maceda'
13
+ },
14
+ year: 33,
15
+ moreArray: [[[50, 40, 10]]]
16
+ },
17
+ ls: {
18
+ users: [
19
+ {
20
+ name: 'sinuhe',
21
+ year: 33
22
+ },
23
+ {
24
+ name: 'alberto',
25
+ year: 20
26
+ }
27
+ ]
28
+ }
29
+ }
30
+
31
+ function increment({ state, set }) {
32
+ set({ channel: state.channel + 1 })
33
+ }
34
+
35
+ function decrement({ state, set }) {
36
+ set({ channel: state.channel - 1 })
37
+ }
38
+
39
+ export default {
40
+ initialState,
41
+ increment,
42
+ decrement
43
+ }
@@ -0,0 +1,211 @@
1
+ import { useEffect } from 'react'
2
+ import './style.css'
3
+ import { css, useFx } from 'nextia'
4
+ import { sum } from 'utils'
5
+ import functions from './functions'
6
+
7
+ export default function HomePage() {
8
+ const { state, initialState, fx, context } = useFx(functions)
9
+
10
+ useEffect(() => {
11
+ console.info(sum(10, 10))
12
+ }, [])
13
+
14
+ return (
15
+ <section className={css('HomePage', 'container')}>
16
+ <div>
17
+ <div>
18
+ <p>set</p>
19
+ <button
20
+ type="button"
21
+ className=""
22
+ onClick={() => fx.set({ setNameValue: 'set 1 level' })}
23
+ >
24
+ set Value
25
+ </button>
26
+ <button
27
+ type="button"
28
+ onClick={() =>
29
+ fx.set({
30
+ form: {
31
+ name: {
32
+ firstName: 'ppppppppppp',
33
+ lastName: '***********'
34
+ }
35
+ }
36
+ })
37
+ }
38
+ >
39
+ set Json
40
+ </button>
41
+ </div>
42
+
43
+ <div>
44
+ <button
45
+ type="button"
46
+ onClick={() => fx.set({ 'form.name.lastName': 'BOUCHAN' })}
47
+ >
48
+ set mulit level (Value)
49
+ </button>
50
+
51
+ <button
52
+ type="button"
53
+ onClick={() =>
54
+ fx.set({
55
+ 'form.name': { firstName: 'SINUHE', lastName: 'MACEDA' }
56
+ })
57
+ }
58
+ >
59
+ set mulit level (Json)
60
+ </button>
61
+ </div>
62
+
63
+ <div>
64
+ <p>Show and Hide :</p>
65
+ <button type="button" onClick={() => fx.show('form.funny')}>
66
+ show
67
+ </button>
68
+ <button type="button" onClick={() => fx.hide('form.funny')}>
69
+ hide
70
+ </button>
71
+ </div>
72
+
73
+ <div>
74
+ <p>Reset :</p>
75
+ <button type="button" onClick={() => fx.reset('ls')}>
76
+ Reset (ls)
77
+ </button>
78
+ <button type="button" onClick={() => fx.reset('form.name')}>
79
+ Reset (form.name)
80
+ </button>
81
+ <button
82
+ type="button"
83
+ onClick={() => fx.reset(['channel', 'msg', 'form.name'])}
84
+ >
85
+ Reset ([channel,msg,form.name])
86
+ </button>
87
+ </div>
88
+
89
+ <div>
90
+ <p>Simple actions/Reducer:</p>
91
+ <button type="button" onClick={(e) => fx.increment(e)}>
92
+ +
93
+ </button>
94
+ <button type="button" onClick={(e) => fx.decrement(e)}>
95
+ -
96
+ </button>
97
+
98
+ <button
99
+ type="button"
100
+ onClick={() =>
101
+ fx.set({
102
+ channel: 256,
103
+ msg: 256,
104
+ data: { user: 256 },
105
+ myArray: ['256', '256', '256'],
106
+ setNameValue: '256',
107
+ form: {
108
+ // funny: 256,
109
+ // gender: '256',
110
+ name: {
111
+ firstName: '256',
112
+ lastName: '256'
113
+ },
114
+ year: 256,
115
+ moreArray: [[[256, 256, 256]]]
116
+ },
117
+ ls: {
118
+ users: [
119
+ {
120
+ name: '256',
121
+ year: 256
122
+ },
123
+ {
124
+ name: '256',
125
+ year: 256
126
+ }
127
+ ]
128
+ }
129
+ })
130
+ }
131
+ >
132
+ 256
133
+ </button>
134
+ </div>
135
+
136
+ <div>
137
+ <p>onChange:</p>
138
+
139
+ {/* input text */}
140
+ <input
141
+ type="text"
142
+ name="form.name.firstName"
143
+ value={state.form.name.firstName}
144
+ onChange={(evt) => fx.change(evt)}
145
+ />
146
+
147
+ {/* checkbox */}
148
+ <input
149
+ type="checkbox"
150
+ name="form.funny"
151
+ checked={state.form.funny}
152
+ onChange={(evt) => fx.change(evt)}
153
+ />
154
+ <label htmlFor="form.funny">Funny</label>
155
+
156
+ {/* radio */}
157
+ <input
158
+ type="radio"
159
+ name="form.gender"
160
+ value="M"
161
+ checked={state.form.gender === 'M'}
162
+ onChange={(evt) => fx.change(evt)}
163
+ />
164
+ <label htmlFor="M">M</label>
165
+ <input
166
+ type="radio"
167
+ name="form.gender"
168
+ value="F"
169
+ checked={state.form.gender === 'F'}
170
+ onChange={(evt) => fx.change(evt)}
171
+ />
172
+ <label htmlFor="F">F</label>
173
+
174
+ {/* select */}
175
+ <select name="form.year" onChange={(evt) => fx.change(evt)}>
176
+ <option value="20">20</option>
177
+ <option value="21">21</option>
178
+ <option value="22">22</option>
179
+ <option value="33">33</option>
180
+ </select>
181
+ </div>
182
+ </div>
183
+
184
+ <div>
185
+ <div style={{ textAlign: 'center' }}>
186
+ <button type="button" onClick={() => fx.reset()}>
187
+ RESET
188
+ </button>
189
+ <button
190
+ type="button"
191
+ onClick={() => {
192
+ if (context.state.loading) context.fx.hide('loading')
193
+ else context.fx.show('loading')
194
+ }}
195
+ >
196
+ loading
197
+ </button>
198
+ </div>
199
+
200
+ <div style={{ display: 'flex' }}>
201
+ <pre style={{ margin: '0 50px 0 50px' }}>
202
+ state = {JSON.stringify(state, undefined, 2)}
203
+ </pre>
204
+ <pre style={{ margin: '0 50px 0 50px' }}>
205
+ initialState = {JSON.stringify(initialState, undefined, 2)}
206
+ </pre>
207
+ </div>
208
+ </div>
209
+ </section>
210
+ )
211
+ }