nextia 7.0.12 → 8.0.1
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/package.json +4 -4
- package/src/bin.js +14 -71
- package/src/lib/fx.js +59 -26
- package/src/lib/index.js +3 -2
- package/src/lib/ui.js +24 -30
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nextia",
|
|
3
3
|
"description": "Create fast web applications",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "8.0.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@vitejs/plugin-react": "6.0.1",
|
|
45
|
-
"@vitest/coverage-v8": "4.1.
|
|
46
|
-
"jsdom": "29.0
|
|
47
|
-
"vitest": "4.1.
|
|
45
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
46
|
+
"jsdom": "29.1.0",
|
|
47
|
+
"vitest": "4.1.5"
|
|
48
48
|
}
|
|
49
49
|
}
|
package/src/bin.js
CHANGED
|
@@ -21,7 +21,7 @@ function toPascalCase(str) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
async function createPage(name) {
|
|
24
|
-
const dirName = `./src/
|
|
24
|
+
const dirName = `./src/app/${name}`
|
|
25
25
|
const pageName = `${toPascalCase(name)}Page`
|
|
26
26
|
|
|
27
27
|
try {
|
|
@@ -30,15 +30,13 @@ async function createPage(name) {
|
|
|
30
30
|
// index.jsx
|
|
31
31
|
writeFile(
|
|
32
32
|
`${dirName}/index.jsx`,
|
|
33
|
-
`import
|
|
34
|
-
import functions from './functions'
|
|
35
|
-
import './style.css'
|
|
33
|
+
`import useFunctions from './functions'
|
|
36
34
|
|
|
37
|
-
export default function ${pageName}
|
|
38
|
-
const { state, fx } =
|
|
35
|
+
export default function ${pageName}() {
|
|
36
|
+
const { state, fx } = useFunctions()
|
|
39
37
|
|
|
40
38
|
return (
|
|
41
|
-
<section
|
|
39
|
+
<section>
|
|
42
40
|
${pageName}
|
|
43
41
|
</section>
|
|
44
42
|
)
|
|
@@ -46,20 +44,18 @@ export default function ${pageName} () {
|
|
|
46
44
|
`
|
|
47
45
|
)
|
|
48
46
|
|
|
49
|
-
// style.sss
|
|
50
|
-
writeFile(
|
|
51
|
-
`${dirName}/style.css`,
|
|
52
|
-
`.${pageName} {
|
|
53
|
-
}
|
|
54
|
-
`
|
|
55
|
-
)
|
|
56
|
-
|
|
57
47
|
// function.js
|
|
58
48
|
writeFile(
|
|
59
49
|
`${dirName}/functions.js`,
|
|
60
|
-
`
|
|
50
|
+
`import { useFx } from 'nextia'
|
|
51
|
+
|
|
52
|
+
export default () => {
|
|
53
|
+
const initialState = {}
|
|
61
54
|
|
|
62
|
-
|
|
55
|
+
return useFx({
|
|
56
|
+
initialState
|
|
57
|
+
})
|
|
58
|
+
}
|
|
63
59
|
`
|
|
64
60
|
)
|
|
65
61
|
console.info(`✔ Page "${pageName}" created at ${dirName}`)
|
|
@@ -81,7 +77,7 @@ async function createComponent(name) {
|
|
|
81
77
|
`import { css } from 'nextia'
|
|
82
78
|
import './style.css'
|
|
83
79
|
|
|
84
|
-
export default function ${componentName}
|
|
80
|
+
export default function ${componentName}({ className, style }) {
|
|
85
81
|
return (
|
|
86
82
|
<article className={css('${componentName}', className)} style={style}>
|
|
87
83
|
${componentName}
|
|
@@ -104,54 +100,6 @@ export default function ${componentName} ({ className, style }) {
|
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
async function createComponentFx(name) {
|
|
108
|
-
const dirName = `./src/components/${name}`
|
|
109
|
-
const componentFxName = toPascalCase(name)
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
await mkdir(dirName)
|
|
113
|
-
|
|
114
|
-
// index.jsx
|
|
115
|
-
writeFile(
|
|
116
|
-
`${dirName}/index.jsx`,
|
|
117
|
-
`import { css, useFx } from 'nextia'
|
|
118
|
-
import functions from './functions'
|
|
119
|
-
import './style.css'
|
|
120
|
-
|
|
121
|
-
export default function ${componentFxName} ({ className, style }) {
|
|
122
|
-
const { state, fx } = useFx(functions)
|
|
123
|
-
|
|
124
|
-
return (
|
|
125
|
-
<article className={css('${componentFxName}', className, '')} style={style}>
|
|
126
|
-
${componentFxName}
|
|
127
|
-
</article>
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
`
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
// style.css
|
|
134
|
-
writeFile(
|
|
135
|
-
`${dirName}/style.css`,
|
|
136
|
-
`.${componentFxName} {
|
|
137
|
-
}
|
|
138
|
-
`
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
// function.js
|
|
142
|
-
writeFile(
|
|
143
|
-
`${dirName}/functions.js`,
|
|
144
|
-
`const initialState = {}
|
|
145
|
-
|
|
146
|
-
export default { initialState }
|
|
147
|
-
`
|
|
148
|
-
)
|
|
149
|
-
console.info(`✔ ComponentFx "${name}" created at ${dirName}`)
|
|
150
|
-
} catch (err) {
|
|
151
|
-
console.error(`Failed to create component:fx: ${err.message}`)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
103
|
async function main() {
|
|
156
104
|
const ARG1 = process.argv[2]
|
|
157
105
|
const ARG2 = process.argv[3]
|
|
@@ -166,11 +114,6 @@ async function main() {
|
|
|
166
114
|
if (ARG2) await createComponent(ARG2)
|
|
167
115
|
else console.warn('node --run component -- <ComponentName>')
|
|
168
116
|
break
|
|
169
|
-
|
|
170
|
-
case 'component:fx':
|
|
171
|
-
if (ARG2) await createComponentFx(ARG2)
|
|
172
|
-
else console.warn('node --run component:fx -- <ComponentFxName>')
|
|
173
|
-
break
|
|
174
117
|
}
|
|
175
118
|
}
|
|
176
119
|
|
package/src/lib/fx.js
CHANGED
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* https://github.com/sinuhedev/nextia
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { createContext, use, useReducer } from 'react'
|
|
10
|
+
import { createContext, use, useEffect, useReducer, useState } from 'react'
|
|
11
11
|
import { env } from './utils.js'
|
|
12
12
|
|
|
13
13
|
const LOGGER = env.DEV && env.PUBLIC_LOGGER !== 'false'
|
|
14
|
-
const
|
|
14
|
+
const Pages = createContext()
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* util
|
|
@@ -69,7 +69,7 @@ const reducer = (state, action) => {
|
|
|
69
69
|
|
|
70
70
|
switch (type) {
|
|
71
71
|
case 'set':
|
|
72
|
-
// Merge
|
|
72
|
+
// Merge custom items
|
|
73
73
|
if (Object.keys(payload).length === 1) {
|
|
74
74
|
const key = Object.keys(payload)[0]
|
|
75
75
|
return values(state, key, payload[key])
|
|
@@ -93,8 +93,19 @@ const reducer = (state, action) => {
|
|
|
93
93
|
: payload.target.value
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
+
case 'toggle':
|
|
97
|
+
// toggle custom items
|
|
98
|
+
if (payload) {
|
|
99
|
+
const paths = Array.isArray(payload) ? payload : [payload]
|
|
100
|
+
|
|
101
|
+
return paths.reduce((ac, path) => {
|
|
102
|
+
const value = path.split('.').reduce((ac, e) => ac[e], state)
|
|
103
|
+
return values(ac, path, !value)
|
|
104
|
+
}, state)
|
|
105
|
+
} else return state
|
|
106
|
+
|
|
96
107
|
case 'reset':
|
|
97
|
-
//
|
|
108
|
+
// reset custom items
|
|
98
109
|
if (payload) {
|
|
99
110
|
const paths = Array.isArray(payload) ? payload : [payload]
|
|
100
111
|
|
|
@@ -133,7 +144,7 @@ const reducerLogger = (state, action) => {
|
|
|
133
144
|
}
|
|
134
145
|
|
|
135
146
|
console.log(
|
|
136
|
-
`%c${action.isContext ? '
|
|
147
|
+
`%c${action.isContext ? 'Context' : 'Page'} %c${action.type}`,
|
|
137
148
|
'color: #90b1d1',
|
|
138
149
|
'color: #6592c8',
|
|
139
150
|
payloadLog(action),
|
|
@@ -144,11 +155,32 @@ const reducerLogger = (state, action) => {
|
|
|
144
155
|
}
|
|
145
156
|
|
|
146
157
|
/**
|
|
147
|
-
* useFx
|
|
158
|
+
* useCx and useFx
|
|
148
159
|
*/
|
|
149
160
|
|
|
161
|
+
function useCx() {
|
|
162
|
+
const pages = use(Pages)
|
|
163
|
+
const [icons, setIcons] = useState()
|
|
164
|
+
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
fetch(pages?.icons)
|
|
167
|
+
.then((r) => r.text())
|
|
168
|
+
.then((text) => {
|
|
169
|
+
setIcons(
|
|
170
|
+
new DOMParser().parseFromString(text, 'image/svg+xml').documentElement
|
|
171
|
+
)
|
|
172
|
+
})
|
|
173
|
+
}, [pages?.icons])
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
context: pages?.context,
|
|
177
|
+
i18n: pages?.i18n,
|
|
178
|
+
icons
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
150
182
|
function useFx(functions = { initialState: {} }) {
|
|
151
|
-
const
|
|
183
|
+
const cx = useCx()
|
|
152
184
|
const { initialState } = functions
|
|
153
185
|
const [state, dispatch] = useReducer(
|
|
154
186
|
LOGGER ? reducerLogger : reducer,
|
|
@@ -156,19 +188,23 @@ function useFx(functions = { initialState: {} }) {
|
|
|
156
188
|
)
|
|
157
189
|
|
|
158
190
|
// Common actions
|
|
159
|
-
const commonActions = [
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
191
|
+
const commonActions = [
|
|
192
|
+
'set',
|
|
193
|
+
'show',
|
|
194
|
+
'hide',
|
|
195
|
+
'change',
|
|
196
|
+
'toggle',
|
|
197
|
+
'reset'
|
|
198
|
+
].reduce((acc, e) => {
|
|
199
|
+
acc[e] = (payload) =>
|
|
200
|
+
dispatch({
|
|
201
|
+
type: e,
|
|
202
|
+
payload,
|
|
203
|
+
initialState,
|
|
204
|
+
isContext: !cx?.context
|
|
205
|
+
})
|
|
206
|
+
return acc
|
|
207
|
+
}, {})
|
|
172
208
|
|
|
173
209
|
// Actions
|
|
174
210
|
const actions = Object.keys(functions).reduce((ac, e) => {
|
|
@@ -178,7 +214,7 @@ function useFx(functions = { initialState: {} }) {
|
|
|
178
214
|
...commonActions,
|
|
179
215
|
state,
|
|
180
216
|
payload,
|
|
181
|
-
context:
|
|
217
|
+
context: cx?.context
|
|
182
218
|
}
|
|
183
219
|
|
|
184
220
|
return functions[e](Object.freeze(actionsProps))
|
|
@@ -192,13 +228,10 @@ function useFx(functions = { initialState: {} }) {
|
|
|
192
228
|
initialState,
|
|
193
229
|
state,
|
|
194
230
|
fx: { ...commonActions, ...actions },
|
|
195
|
-
|
|
196
|
-
context: pagesFx?.context,
|
|
197
|
-
iconsFile: pagesFx?.iconsFile,
|
|
198
|
-
i18nFile: pagesFx?.i18nFile
|
|
231
|
+
context: cx.context
|
|
199
232
|
}
|
|
200
233
|
|
|
201
234
|
return Object.freeze(props)
|
|
202
235
|
}
|
|
203
236
|
|
|
204
|
-
export {
|
|
237
|
+
export { Pages, useCx, useFx }
|
package/src/lib/index.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* https://github.com/sinuhedev/nextia
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { Pages, useCx, useFx } from './fx.js'
|
|
11
11
|
import { useQueryString, useResize } from './hooks.js'
|
|
12
12
|
import { I18n, Icon, Link, Svg } from './ui.js'
|
|
13
13
|
import { css, env, startViewTransition } from './utils.js'
|
|
@@ -18,9 +18,10 @@ export {
|
|
|
18
18
|
I18n,
|
|
19
19
|
Icon,
|
|
20
20
|
Link,
|
|
21
|
-
|
|
21
|
+
Pages,
|
|
22
22
|
Svg,
|
|
23
23
|
startViewTransition,
|
|
24
|
+
useCx,
|
|
24
25
|
useFx,
|
|
25
26
|
useQueryString,
|
|
26
27
|
useResize
|
package/src/lib/ui.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { createElement, useEffect, useRef } from 'react'
|
|
11
|
-
import {
|
|
11
|
+
import { useCx } from './fx'
|
|
12
12
|
|
|
13
13
|
function Link({ children, href, value = {}, ...props }) {
|
|
14
14
|
href ??= window.location.hash.split('?')[0]
|
|
@@ -20,18 +20,14 @@ function Link({ children, href, value = {}, ...props }) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function I18n({ value, args = [] }) {
|
|
23
|
-
const { context,
|
|
23
|
+
const { context, i18n } = useCx()
|
|
24
24
|
|
|
25
|
-
if (
|
|
25
|
+
if (i18n) {
|
|
26
26
|
try {
|
|
27
|
-
let text = value.split('.').reduce((ac, el) => ac[el],
|
|
27
|
+
let text = value.split('.').reduce((ac, el) => ac[el], i18n)
|
|
28
28
|
|
|
29
29
|
text =
|
|
30
|
-
text[
|
|
31
|
-
i18nFile.locales.indexOf(
|
|
32
|
-
context.state?.i18n || i18nFile.defaultLocale
|
|
33
|
-
)
|
|
34
|
-
]
|
|
30
|
+
text[i18n.locales.indexOf(context.state?.i18n || i18n.defaultLocale)]
|
|
35
31
|
|
|
36
32
|
if (args) {
|
|
37
33
|
text = text.replace(
|
|
@@ -64,20 +60,14 @@ function Icon({
|
|
|
64
60
|
strokeLinejoin = 'round',
|
|
65
61
|
...props
|
|
66
62
|
}) {
|
|
67
|
-
const {
|
|
63
|
+
const { icons } = useCx()
|
|
68
64
|
const ref = useRef()
|
|
69
65
|
|
|
70
66
|
useEffect(() => {
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
.parseFromString(iconsFile, 'image/svg+xml')
|
|
74
|
-
.documentElement.getElementById(id)
|
|
75
|
-
|
|
76
|
-
if (svg) {
|
|
77
|
-
ref.current.innerHTML = svg.innerHTML
|
|
78
|
-
}
|
|
67
|
+
if (icons) {
|
|
68
|
+
ref.current.innerHTML = icons.getElementById(id).innerHTML
|
|
79
69
|
}
|
|
80
|
-
}, [id,
|
|
70
|
+
}, [id, icons])
|
|
81
71
|
|
|
82
72
|
return createElement('svg', {
|
|
83
73
|
xmlns: 'http://www.w3.org/2000/svg',
|
|
@@ -102,17 +92,21 @@ function Svg({ ref, src, width, height, ...props }) {
|
|
|
102
92
|
ref ??= useRef()
|
|
103
93
|
|
|
104
94
|
useEffect(() => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
95
|
+
fetch(src)
|
|
96
|
+
.then((r) => r.text())
|
|
97
|
+
.then((text) => {
|
|
98
|
+
const svg = new DOMParser().parseFromString(
|
|
99
|
+
text,
|
|
100
|
+
'image/svg+xml'
|
|
101
|
+
).documentElement
|
|
102
|
+
|
|
103
|
+
for (const { name, value } of svg.attributes) {
|
|
104
|
+
if (name !== 'width' && name !== 'height')
|
|
105
|
+
ref.current.setAttribute(name, value)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
ref.current.replaceChildren(...svg.children)
|
|
109
|
+
})
|
|
116
110
|
}, [src, ref])
|
|
117
111
|
|
|
118
112
|
return createElement('svg', {
|