nextia 5.0.2 → 6.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 CHANGED
@@ -1,9 +1,7 @@
1
1
  # nextia
2
+ Create fast web applications
2
3
 
3
- ## Create fast web applications
4
-
5
- Go to test
6
-
4
+ ### To start
7
5
  ```sh
8
6
  npm install
9
7
  pnpm install
@@ -11,8 +9,7 @@ pnpm install
11
9
  cd test
12
10
  ```
13
11
 
14
- commands
15
-
12
+ ### To test
16
13
  ```sh
17
14
  npm install
18
15
  pnpm install
@@ -20,11 +17,10 @@ pnpm install
20
17
  node --run test:my-app
21
18
  ```
22
19
 
23
- create project
24
-
20
+ ### To create project
25
21
  ```sh
26
- npx nextia@latest my-app
27
- pnpx nextia@latest my-app
22
+ pnpm i -g nextia
23
+ nextia my-app
28
24
  ```
29
25
 
30
- [npm](https://www.npmjs.com/package/nextia)
26
+ [npmjs.com/package/nextia](https://www.npmjs.com/package/nextia)
package/biome.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3
+ "assist": {
4
+ "actions": {
5
+ "source": {
6
+ "organizeImports": "off"
7
+ }
8
+ }
9
+ },
10
+ "linter": {
11
+ "enabled": true,
12
+ "rules": {
13
+ "recommended": true,
14
+ "correctness": {
15
+ "noUnusedVariables": "error"
16
+ }
17
+ }
18
+ },
19
+ "formatter": {
20
+ "enabled": true,
21
+ "formatWithErrors": false,
22
+ "indentStyle": "space",
23
+ "indentWidth": 2
24
+ },
25
+ "javascript": {
26
+ "formatter": {
27
+ "semicolons": "asNeeded",
28
+ "quoteStyle": "single",
29
+ "jsxQuoteStyle": "double",
30
+ "trailingCommas": "none"
31
+ }
32
+ },
33
+ "css": {
34
+ "formatter": {
35
+ "enabled": true
36
+ }
37
+ },
38
+ "json": {
39
+ "formatter": {
40
+ "enabled": true
41
+ }
42
+ }
43
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nextia",
3
3
  "description": "Create fast web applications",
4
- "version": "5.0.2",
4
+ "version": "6.0.0",
5
5
  "engines": {
6
6
  "node": ">22"
7
7
  },
@@ -24,19 +24,18 @@
24
24
  "nextia": "src/bin.js"
25
25
  },
26
26
  "main": "src/lib.js",
27
- "eslintConfig": {
28
- "extends": "./node_modules/standard/eslintrc.json"
29
- },
30
27
  "peerDependencies": {
31
28
  "react": "^19.2.3",
32
29
  "react-dom": "^19.2.3"
33
30
  },
34
31
  "devDependencies": {
35
- "standard": "^17.1.2"
32
+ "@biomejs/biome": "^2.3.14"
36
33
  },
37
34
  "scripts": {
38
35
  "clean": "rm -fr node_modules package-lock.json pnpm-lock.yaml .coverage out my-app",
39
- "lint": "standard 'src/**/*.{js,jsx}' 'test/**/*.{js,jsx}' --verbose",
36
+ "format": "biome format",
37
+ "lint": "biome lint",
38
+ "check": "biome check --reporter=summary",
40
39
  "test": "node src/bin.js",
41
40
  "test:my-app": "node src/bin.js my-app"
42
41
  }
package/src/bin.js CHANGED
@@ -9,18 +9,26 @@
9
9
  * https://github.com/sinuhedev/nextia
10
10
  */
11
11
 
12
- import pkg from "../package.json" with { type: "json" };
12
+ import pkg from '../package.json' with { type: 'json' }
13
13
  import { fileURLToPath } from 'node:url'
14
14
  import { dirname } from 'node:path'
15
- import { mkdir, writeFile, readFile, cp, rename, access } from 'node:fs/promises'
16
-
17
- async function createPage (name) {
18
- const toPascalCase = str => str
19
- .toLowerCase()
20
- .replace(/[^a-zA-Z0-9 ]/g, ' ') // replace special characters
21
- .split(/\s+/) // split by spaces
22
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
23
- .join('')
15
+ import {
16
+ mkdir,
17
+ writeFile,
18
+ readFile,
19
+ cp,
20
+ rename,
21
+ access
22
+ } from 'node:fs/promises'
23
+
24
+ async function createPage(name) {
25
+ const toPascalCase = (str) =>
26
+ str
27
+ .toLowerCase()
28
+ .replace(/[^a-zA-Z0-9 ]/g, ' ') // replace special characters
29
+ .split(/\s+/) // split by spaces
30
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
31
+ .join('')
24
32
 
25
33
  const dirName = `./src/pages/${name}`
26
34
 
@@ -30,8 +38,9 @@ async function createPage (name) {
30
38
  const pageName = toPascalCase(name) + 'Page'
31
39
 
32
40
  // index.jsx
33
- writeFile(`${dirName}/index.jsx`,
34
- `import React, { useEffect } from 'react'
41
+ writeFile(
42
+ `${dirName}/index.jsx`,
43
+ `import React, { useEffect } from 'react'
35
44
  import { useFx, css } from 'nextia'
36
45
  import functions from './functions'
37
46
  import './style.css'
@@ -45,26 +54,31 @@ export default function ${pageName} () {
45
54
  </section>
46
55
  )
47
56
  }
48
- `)
57
+ `
58
+ )
49
59
 
50
60
  // style.sss
51
- writeFile(`${dirName}/style.css`,
52
- `.${pageName} {
53
- }`)
61
+ writeFile(
62
+ `${dirName}/style.css`,
63
+ `.${pageName} {
64
+ }`
65
+ )
54
66
 
55
67
  // function.js
56
- writeFile(`${dirName}/functions.js`,
57
- `const initialState = {
68
+ writeFile(
69
+ `${dirName}/functions.js`,
70
+ `const initialState = {
58
71
  }
59
72
 
60
73
  export default { initialState }
61
- `)
74
+ `
75
+ )
62
76
  } catch (err) {
63
77
  console.error(err)
64
78
  }
65
79
  }
66
80
 
67
- async function createComponent (name) {
81
+ async function createComponent(name) {
68
82
  const dirName = `./src/components/${name}`
69
83
 
70
84
  try {
@@ -72,8 +86,9 @@ async function createComponent (name) {
72
86
  const componentName = name.replaceAll('/', '') + '-component'
73
87
 
74
88
  // index.jsx
75
- writeFile(`${dirName}/index.jsx`,
76
- `import React, { useEffect } from 'react'
89
+ writeFile(
90
+ `${dirName}/index.jsx`,
91
+ `import React, { useEffect } from 'react'
77
92
  import { css } from 'nextia'
78
93
  import './style.css'
79
94
 
@@ -84,11 +99,13 @@ export default function ${name} ({ className, style }) {
84
99
  </article>
85
100
  )
86
101
  }
87
- `)
102
+ `
103
+ )
88
104
 
89
105
  // style.css
90
- writeFile(`${dirName}/style.css`,
91
- `.${componentName} {
106
+ writeFile(
107
+ `${dirName}/style.css`,
108
+ `.${componentName} {
92
109
  }`
93
110
  )
94
111
  } catch (err) {
@@ -96,7 +113,7 @@ export default function ${name} ({ className, style }) {
96
113
  }
97
114
  }
98
115
 
99
- async function createComponentFx (name) {
116
+ async function createComponentFx(name) {
100
117
  const dirName = `./src/components/${name}`
101
118
 
102
119
  try {
@@ -104,8 +121,9 @@ async function createComponentFx (name) {
104
121
  const containerName = name.replaceAll('/', '') + '-component'
105
122
 
106
123
  // index.jsx
107
- writeFile(`${dirName}/index.jsx`,
108
- `import React, { useEffect } from 'react'
124
+ writeFile(
125
+ `${dirName}/index.jsx`,
126
+ `import React, { useEffect } from 'react'
109
127
  import { useFx, css } from 'nextia'
110
128
  import functions from './functions'
111
129
  import './style.css'
@@ -119,26 +137,31 @@ export default function ${name} ({ className, style }) {
119
137
  </article>
120
138
  )
121
139
  }
122
- `)
140
+ `
141
+ )
123
142
 
124
143
  // style.css
125
- writeFile(`${dirName}/style.css`,
126
- `.${containerName} {
127
- }`)
144
+ writeFile(
145
+ `${dirName}/style.css`,
146
+ `.${containerName} {
147
+ }`
148
+ )
128
149
 
129
150
  // function.js
130
- writeFile(`${dirName}/functions.js`,
131
- `const initialState = {
151
+ writeFile(
152
+ `${dirName}/functions.js`,
153
+ `const initialState = {
132
154
  }
133
155
 
134
156
  export default { initialState }
135
- `)
157
+ `
158
+ )
136
159
  } catch (err) {
137
160
  console.error(err)
138
161
  }
139
162
  }
140
163
 
141
- async function createProject (name) {
164
+ async function createProject(name) {
142
165
  let projectPath
143
166
 
144
167
  try {
@@ -146,14 +169,14 @@ async function createProject (name) {
146
169
  await access(projectPath)
147
170
  console.error(`The "${name}" already exists.`)
148
171
  return
149
- } catch (error) {
150
- }
172
+ } catch (error) {}
151
173
 
152
174
  const template = dirname(fileURLToPath(import.meta.url)) + '/template/'
153
175
 
154
176
  // Create new project
155
177
  try {
156
- const mv = fileName => rename(projectPath + `_${fileName}`, projectPath + `.${fileName}`)
178
+ const mv = (fileName) =>
179
+ rename(projectPath + `_${fileName}`, projectPath + `.${fileName}`)
157
180
  await cp(template, projectPath, { recursive: true })
158
181
  const replaceToken = async (filename, token, value) => {
159
182
  const content = await readFile(projectPath + filename, 'utf8')
@@ -200,7 +223,8 @@ switch (ARG1) {
200
223
 
201
224
  default:
202
225
  if (ARG1) createProject(ARG1)
203
- else console.info(`
226
+ else
227
+ console.info(`
204
228
  Version ${pkg.version}
205
229
 
206
230
  npx nextia@latest <ProjectName>
package/src/lib.js CHANGED
@@ -14,13 +14,16 @@ const Context = createContext()
14
14
  /**
15
15
  * css
16
16
  */
17
- function css (...classNames) {
17
+ function css(...classNames) {
18
18
  classNames = classNames
19
- .filter(e => e)
19
+ .filter((e) => e)
20
20
  .reduce((accumulator, currentValue) => {
21
21
  if (typeof currentValue === 'string') {
22
22
  accumulator.push(currentValue)
23
- } else if (!Array.isArray(currentValue) && typeof currentValue === 'object') {
23
+ } else if (
24
+ !Array.isArray(currentValue) &&
25
+ typeof currentValue === 'object'
26
+ ) {
24
27
  for (const e in currentValue) {
25
28
  if (currentValue[e]) accumulator.push(e)
26
29
  }
@@ -28,13 +31,13 @@ function css (...classNames) {
28
31
  return accumulator
29
32
  }, [])
30
33
 
31
- return ([...new Set(classNames)]).join(' ')
34
+ return [...new Set(classNames)].join(' ')
32
35
  }
33
36
 
34
37
  /**
35
38
  * values
36
39
  */
37
- function values (state, payload, value) {
40
+ function values(state, payload, value) {
38
41
  const paths = payload.split('.')
39
42
 
40
43
  // one level
@@ -63,15 +66,15 @@ function values (state, payload, value) {
63
66
  /**
64
67
  * merge
65
68
  */
66
- function merge (target, source) {
69
+ function merge(target, source) {
67
70
  // in array return all source
68
71
  if (Array.isArray(target)) return source
69
72
 
70
- const isObject = obj => obj && typeof obj === 'object'
73
+ const isObject = (obj) => obj && typeof obj === 'object'
71
74
  const output = { ...target }
72
75
 
73
76
  // merge
74
- Object.keys(source).forEach(key => {
77
+ Object.keys(source).forEach((key) => {
75
78
  if (isObject(target[key]) && isObject(source[key])) {
76
79
  output[key] = merge(target[key], source[key])
77
80
  } else output[key] = structuredClone(source[key])
@@ -97,7 +100,10 @@ const log = (reducer) => {
97
100
  if (type === 'change') {
98
101
  const { name, type, checked, value } = payload.target
99
102
  return {
100
- name, type, checked, value
103
+ name,
104
+ type,
105
+ checked,
106
+ value
101
107
  }
102
108
  }
103
109
 
@@ -108,16 +114,22 @@ const log = (reducer) => {
108
114
  return payload
109
115
  }
110
116
 
111
- const reducerWithLogger = useCallback((state, action) => {
112
- const newState = reducer(state, action)
117
+ const reducerWithLogger = useCallback(
118
+ (state, action) => {
119
+ const newState = reducer(state, action)
113
120
 
114
- console.log(
115
- `%c${action.isContext ? 'Context' : 'Page '} %c${action.type}`, 'color: #90b1d1', 'color: #6592c8',
116
- getPayload(action), { state, new_state: newState }
117
- )
121
+ console.log(
122
+ `%c${action.isContext ? 'Context' : 'Page '} %c${action.type}`,
123
+ 'color: #90b1d1',
124
+ 'color: #6592c8',
125
+ getPayload(action),
126
+ { state, new_state: newState }
127
+ )
118
128
 
119
- return newState
120
- }, [reducer])
129
+ return newState
130
+ },
131
+ [reducer]
132
+ )
121
133
 
122
134
  return reducerWithLogger
123
135
  }
@@ -149,7 +161,9 @@ const reducer = (state, action) => {
149
161
  return values(
150
162
  state,
151
163
  payload.target.name,
152
- payload.target.type === 'checkbox' ? payload.target.checked : payload.target.value
164
+ payload.target.type === 'checkbox'
165
+ ? payload.target.checked
166
+ : payload.target.value
153
167
  )
154
168
 
155
169
  case 'reset':
@@ -171,27 +185,36 @@ const reducer = (state, action) => {
171
185
  /**
172
186
  * useFx
173
187
  */
174
- function useFx (functions = { initialState: {} }) {
188
+ function useFx(functions = { initialState: {} }) {
175
189
  const context = use(Context)
176
190
  const { initialState } = functions
177
- const [state, dispatch] = useReducer(logger() ? log(reducer) : reducer, initialState)
191
+ const [state, dispatch] = useReducer(
192
+ logger() ? log(reducer) : reducer,
193
+ initialState
194
+ )
178
195
 
179
196
  // Common actions
180
- const commonActions = ['set', 'show', 'hide', 'change', 'reset'].reduce((acc, e) => {
181
- acc[e] = payload => dispatch({ type: e, payload, initialState, isContext: !context })
182
- return acc
183
- }, {})
197
+ const commonActions = ['set', 'show', 'hide', 'change', 'reset'].reduce(
198
+ (acc, e) => {
199
+ acc[e] = (payload) =>
200
+ dispatch({ type: e, payload, initialState, isContext: !context })
201
+ return acc
202
+ },
203
+ {}
204
+ )
184
205
 
185
206
  // Actions
186
207
  const actions = Object.keys(functions).reduce((ac, e) => {
187
208
  if (functions[e] instanceof Function) {
188
- ac[e] = payload => {
209
+ ac[e] = (payload) => {
189
210
  const props = {
190
211
  ...commonActions,
191
212
  state,
192
213
  payload
193
214
  }
194
- if (context) { props.context = context }
215
+ if (context) {
216
+ props.context = context
217
+ }
195
218
 
196
219
  return functions[e](Object.freeze(props))
197
220
  }
@@ -205,7 +228,9 @@ function useFx (functions = { initialState: {} }) {
205
228
  state,
206
229
  fx: { ...commonActions, ...actions }
207
230
  }
208
- if (context) { props.context = context }
231
+ if (context) {
232
+ props.context = context
233
+ }
209
234
 
210
235
  return Object.freeze(props)
211
236
  }
@@ -1,7 +1,6 @@
1
1
  # TEMPLATE
2
2
 
3
- ## To start
4
-
3
+ # To start
5
4
  Open http://localhost:3000 to view it in the browser.
6
5
 
7
6
  ```sh
@@ -14,8 +13,7 @@ node --run build <ENV>
14
13
  node --run preview
15
14
  ```
16
15
 
17
- ## env
18
-
16
+ # env
19
17
  ```.env
20
18
  .env # loaded in all cases
21
19
  .env.[ENV] # only loaded in specified ENV [ dev, test, prod ]
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3
+ "assist": {
4
+ "actions": {
5
+ "source": {
6
+ "organizeImports": "off"
7
+ }
8
+ }
9
+ },
10
+ "linter": {
11
+ "enabled": true,
12
+ "rules": {
13
+ "recommended": true,
14
+ "correctness": {
15
+ "noUnusedVariables": "error"
16
+ }
17
+ }
18
+ },
19
+ "formatter": {
20
+ "enabled": true,
21
+ "formatWithErrors": false,
22
+ "indentStyle": "space",
23
+ "indentWidth": 2
24
+ },
25
+ "javascript": {
26
+ "formatter": {
27
+ "semicolons": "asNeeded",
28
+ "quoteStyle": "single",
29
+ "jsxQuoteStyle": "double",
30
+ "trailingCommas": "none"
31
+ }
32
+ },
33
+ "css": {
34
+ "formatter": {
35
+ "enabled": true
36
+ }
37
+ },
38
+ "json": {
39
+ "formatter": {
40
+ "enabled": true
41
+ }
42
+ }
43
+ }
@@ -1,38 +1,41 @@
1
1
  {
2
- "name": "TEMPLATE",
3
- "description": "description",
4
- "version": "0.0.0",
5
- "type": "module",
6
- "private": true,
7
- "eslintConfig": {
8
- "extends": "./node_modules/standard/eslintrc.json"
9
- },
10
- "scripts": {
11
- "dev": "vite --mode dev",
12
- "clean": "rm -fr node_modules package-lock.json pnpm-lock.yaml .coverage out",
13
- "build": "vite build --mode",
14
- "preview": "vite preview",
15
- "lint": "standard 'src/**/*.{js,jsx}' 'test/**/*.{js,jsx}' --verbose",
16
- "page": "nextia page",
17
- "component": "nextia component",
18
- "componentFx": "nextia componentFx",
19
- "test": "vitest",
20
- "test:name": "vitest --testNamePattern",
21
- "test:silent": "vitest --silent",
22
- "test:coverage": "vitest --silent --coverage"
23
- },
24
- "devDependencies": {
25
- "@vitejs/plugin-react": "^5.1.2",
26
- "@vitest/coverage-v8": "^3.2.4",
27
- "autoprefixer": "^10.4.23",
28
- "jsdom": "^26.1.0",
29
- "standard": "^17.1.2",
30
- "vite": "^7.3.1",
31
- "vitest": "^3.2.4"
32
- },
33
- "dependencies": {
34
- "nextia": "^VERSION",
35
- "react": "^19.2.3",
36
- "react-dom": "^19.2.3"
37
- }
38
- }
2
+ "name": "TEMPLATE",
3
+ "description": "description",
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "private": true,
7
+ "eslintConfig": {
8
+ "extends": "./node_modules/standard/eslintrc.json"
9
+ },
10
+ "scripts": {
11
+ "dev": "vite --mode dev",
12
+ "clean": "rm -fr node_modules package-lock.json pnpm-lock.yaml .coverage out",
13
+ "build": "vite build --mode",
14
+ "preview": "vite preview",
15
+ "format": "biome format",
16
+ "lint": "biome lint",
17
+ "check": "biome check --reporter=summary",
18
+ "page": "nextia page",
19
+ "component": "nextia component",
20
+ "componentFx": "nextia componentFx",
21
+ "test": "vitest",
22
+ "test:name": "vitest run --testNamePattern",
23
+ "test:silent": "vitest run --silent",
24
+ "test:coverage": "vitest run --silent --coverage"
25
+ },
26
+ "devDependencies": {
27
+ "@biomejs/biome": "^2.3.14",
28
+ "@vitejs/plugin-react": "^5.1.3",
29
+ "@vitest/coverage-v8": "4.0.18",
30
+ "autoprefixer": "^10.4.24",
31
+ "jsdom": "^28.0.0",
32
+ "standard": "^17.1.2",
33
+ "vite": "^7.3.1",
34
+ "vitest": "4.0.18"
35
+ },
36
+ "dependencies": {
37
+ "nextia": "^VERSION",
38
+ "react": "^19.2.4",
39
+ "react-dom": "^19.2.4"
40
+ }
41
+ }
@@ -1,7 +1,7 @@
1
1
  import { useFx } from 'nextia'
2
2
  import i18nFile from 'assets/i18n'
3
3
 
4
- export default function I18n ({ value, args = [] }) {
4
+ export default function I18n({ value, args = [] }) {
5
5
  const { context } = useFx()
6
6
 
7
7
  try {
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useRef } from 'react'
2
2
  import icons from 'theme/icons/icons.svg?raw'
3
3
 
4
- export default function Icon ({
4
+ export default function Icon({
5
5
  id,
6
6
  className,
7
7
  style,
@@ -18,7 +18,8 @@ export default function Icon ({
18
18
  const ref = useRef()
19
19
 
20
20
  useEffect(() => {
21
- const svg = new window.DOMParser().parseFromString(icons, 'image/svg+xml')
21
+ const svg = new window.DOMParser()
22
+ .parseFromString(icons, 'image/svg+xml')
22
23
  .documentElement.getElementById(id)
23
24
 
24
25
  if (svg) {
@@ -28,7 +29,7 @@ export default function Icon ({
28
29
 
29
30
  return (
30
31
  <svg
31
- xmlns='http://www.w3.org/2000/svg'
32
+ xmlns="http://www.w3.org/2000/svg"
32
33
  ref={ref}
33
34
  id={id}
34
35
  className={className}
@@ -1,8 +1,10 @@
1
1
  import React from 'react'
2
2
 
3
- export default function Link ({ children, href, value = {}, ...props }) {
3
+ export default function Link({ children, href, value = {}, ...props }) {
4
4
  href ??= window.location.hash.split('?')[0]
5
- value = Object.keys(value).length ? '?' + new URLSearchParams(value).toString() : ''
5
+ value = Object.keys(value).length
6
+ ? '?' + new URLSearchParams(value).toString()
7
+ : ''
6
8
 
7
9
  return (
8
10
  <a href={href + value} {...props}>
@@ -3,28 +3,29 @@ import { useFx, css } from 'nextia'
3
3
  import i18nFile from 'assets/i18n'
4
4
  import './style.css'
5
5
 
6
- export default function Translate ({ className, style }) {
6
+ export default function Translate({ className, style }) {
7
7
  const { context } = useFx()
8
8
 
9
9
  return (
10
- <article className={css('Translate-component', className, '')} style={style}>
11
-
10
+ <article
11
+ className={css('Translate-component', className, '')}
12
+ style={style}
13
+ >
12
14
  <select
13
- name='i18n'
15
+ name="i18n"
14
16
  value={context.state.i18n}
15
- onChange={e => {
17
+ onChange={(e) => {
16
18
  const { value } = e.target
17
19
  context.fx.set({ i18n: value })
18
20
  window.localStorage.setItem('i18n', value)
19
21
  }}
20
22
  >
21
- {i18nFile.locales.map(e => (
22
- <option key={e} value={e} className='m-2'>
23
+ {i18nFile.locales.map((e) => (
24
+ <option key={e} value={e} className="m-2">
23
25
  {e}
24
26
  </option>
25
27
  ))}
26
28
  </select>
27
-
28
29
  </article>
29
30
  )
30
31
  }
@@ -1 +1,2 @@
1
- .Translate-component {}
1
+ .Translate-component {
2
+ }
@@ -1,4 +1,3 @@
1
- const initialState = {
2
- }
1
+ const initialState = {}
3
2
 
4
3
  export default { initialState }
@@ -3,12 +3,8 @@ import { useFx, css } from 'nextia'
3
3
  import functions from './functions'
4
4
  import './style.css'
5
5
 
6
- export default function DemoPage () {
6
+ export default function DemoPage() {
7
7
  const { state, fx } = useFx(functions)
8
8
 
9
- return (
10
- <section className={css('DemoPage', '')}>
11
- DemoPage
12
- </section>
13
- )
9
+ return <section className={css('DemoPage', '')}>DemoPage</section>
14
10
  }
@@ -1,2 +1,2 @@
1
1
  .DemoPage {
2
- }
2
+ }
@@ -28,11 +28,11 @@ const initialState = {
28
28
  }
29
29
  }
30
30
 
31
- function increment ({ state, set }) {
31
+ function increment({ state, set }) {
32
32
  set({ channel: state.channel + 1 })
33
33
  }
34
34
 
35
- function decrement ({ state, set }) {
35
+ function decrement({ state, set }) {
36
36
  set({ channel: state.channel - 1 })
37
37
  }
38
38
 
@@ -3,12 +3,8 @@ import './style.css'
3
3
  import { useFx, css } from 'nextia'
4
4
  import functions from './functions'
5
5
 
6
- export default function HomePage () {
6
+ export default function HomePage() {
7
7
  const { state, initialState, fx, context } = useFx(functions)
8
8
 
9
- return (
10
- <section className={css('HomePage', 'container')}>
11
- homePage
12
- </section>
13
- )
9
+ return <section className={css('HomePage', 'container')}>homePage</section>
14
10
  }
@@ -1 +1,2 @@
1
- .HomePage {}
1
+ .HomePage {
2
+ }
@@ -2,12 +2,14 @@ import React, { useEffect } from 'react'
2
2
  import { css } from 'nextia'
3
3
  import './style.css'
4
4
 
5
- export default function HttpNotFoundPage () {
5
+ export default function HttpNotFoundPage() {
6
6
  return (
7
- <section className={css('HttpNotFoundPage', 'd-flex justify-content-center')}>
8
- <div className='d-flex align-items-center'>
9
- <div className='d-flex flex-column'>
10
- <div className='text-center'>
7
+ <section
8
+ className={css('HttpNotFoundPage', 'd-flex justify-content-center')}
9
+ >
10
+ <div className="d-flex align-items-center">
11
+ <div className="d-flex flex-column">
12
+ <div className="text-center">
11
13
  <h5>Not Found</h5>
12
14
  </div>
13
15
  </div>
@@ -1 +1,2 @@
1
- .HttpNotFoundPage {}
1
+ .HttpNotFoundPage {
2
+ }
@@ -4,7 +4,7 @@ import { Translate, I18n, Icon, Link } from 'components'
4
4
  import functions from './functions.js'
5
5
  import { startViewTransition, useQueryString } from 'utils'
6
6
 
7
- export default function Pages () {
7
+ export default function Pages() {
8
8
  const self = useFx(functions)
9
9
  const { state, fx } = self
10
10
 
@@ -37,28 +37,29 @@ export default function Pages () {
37
37
  return (
38
38
  <Context value={self}>
39
39
  <header style={{ display: 'flex', gap: '20px' }}>
40
- <Icon id='globe' width='24' />
40
+ <Icon id="globe" width="24" />
41
41
 
42
- <Translate value={state.i18nLocale} onChange={e => fx.changeI18n(e)} />
42
+ <Translate
43
+ value={state.i18nLocale}
44
+ onChange={(e) => fx.changeI18n(e)}
45
+ />
43
46
 
44
- <I18n value='page.name' args={['Sinuhe', 'Maceda', 'Bouchan']} />
47
+ <I18n value="page.name" args={['Sinuhe', 'Maceda', 'Bouchan']} />
45
48
 
46
- <Link href='/' className='mr-2'>
49
+ <Link href="/" className="mr-2">
47
50
  /
48
51
  </Link>
49
- <Link href='#/' className='mr-2'>
52
+ <Link href="#/" className="mr-2">
50
53
  /home
51
54
  </Link>
52
- <Link href='#/demo' className='mr-2'>
55
+ <Link href="#/demo" className="mr-2">
53
56
  /demo
54
57
  </Link>
55
-
56
58
  </header>
57
59
 
58
- <main ref={ref} className='m-2'>
60
+ <main ref={ref} className="m-2">
59
61
  {Page && <Page qs={qs.queryString} />}
60
62
  </main>
61
-
62
63
  </Context>
63
64
  )
64
65
  }
@@ -3,7 +3,7 @@
3
3
  }
4
4
 
5
5
  /**
6
- * fade
6
+ * fade
7
7
  */
8
8
 
9
9
  @keyframes fade {
@@ -27,4 +27,4 @@
27
27
 
28
28
  ::view-transition-old(fade) {
29
29
  --end: 0;
30
- }
30
+ }
@@ -3,5 +3,5 @@
3
3
  font-style: normal;
4
4
  font-display: swap;
5
5
  font-weight: bold;
6
- src: url('./Roboto-Regular.ttf');
7
- }
6
+ src: url("./Roboto-Regular.ttf");
7
+ }
@@ -1,57 +1 @@
1
- .exit-anim {
2
- --primary-color: #821e8f;
3
-
4
- transition: transform 200ms linear 0ms;
5
-
6
- #animation {
7
- transition: stroke-dashoffset 400ms linear 0ms, stroke-dasharray 400ms linear 0ms;
8
- stroke: var(--primary-color);
9
- stroke-dasharray: 1, 200;
10
- stroke-dashoffset: 1;
11
- }
12
-
13
- #arrow {
14
- animation: arrow 2s ease-in-out infinite;
15
-
16
- #right,
17
- #left {
18
- display: none;
19
- }
20
- }
21
-
22
- &:hover {
23
- transform: rotate(-90deg);
24
-
25
- #animation {
26
- stroke-dasharray: 200, 1;
27
- }
28
-
29
- #arrow {
30
- transform: translateY(2px);
31
- stroke: var(--primary-color);
32
-
33
- line {
34
- stroke-width: 6px;
35
- }
36
-
37
- #right,
38
- #left {
39
- display: block;
40
- }
41
- }
42
- }
43
- }
44
-
45
- @keyframes arrow {
46
- 0% {
47
- transform: translateY(2px);
48
- }
49
-
50
- 50% {
51
- transform: translateY(6px);
52
- }
53
-
54
- 100% {
55
- transform: translateY(2px);
56
- }
57
- }
1
+ /* icons */
@@ -1,15 +1,15 @@
1
- @import './util.css';
2
- @import './fonts/index.css';
3
- @import './icons/index.css';
4
- @import './animations.css';
1
+ @import "./util.css";
2
+ @import "./fonts/index.css";
3
+ @import "./icons/index.css";
4
+ @import "./animations.css";
5
5
 
6
6
  :root {
7
- --primary-color: #344188;
8
- --primary-color-50: #3441887a;
9
- --link: #5fac9f;
10
- --body-bg: #282c34;
11
- --body-color: #a8a8a8;
12
- --font-family: 'Roboto'
7
+ --primary-color: #344188;
8
+ --primary-color-50: #3441887a;
9
+ --link: #5fac9f;
10
+ --body-bg: #282c34;
11
+ --body-color: #a8a8a8;
12
+ --font-family: "Roboto";
13
13
  }
14
14
 
15
15
  /**
@@ -18,23 +18,23 @@
18
18
 
19
19
  html,
20
20
  body {
21
- background-color: var(--body-bg);
22
- color: var(--body-color);
23
- font-family: var(--font-family);
21
+ background-color: var(--body-bg);
22
+ color: var(--body-color);
23
+ font-family: var(--font-family);
24
24
  }
25
25
 
26
26
  a {
27
- color: var(--link);
27
+ color: var(--link);
28
28
  }
29
29
 
30
30
  .mr-2 {
31
- margin-right: 20px;
31
+ margin-right: 20px;
32
32
  }
33
33
 
34
34
  .m-2 {
35
- margin: 20px;
35
+ margin: 20px;
36
36
  }
37
37
 
38
38
  .p-2 {
39
- padding: 20px;
40
- }
39
+ padding: 20px;
40
+ }
@@ -24,4 +24,4 @@
24
24
  ::-webkit-scrollbar-corner {
25
25
  background-color: transparent;
26
26
  }
27
- }
27
+ }
@@ -1,9 +1,11 @@
1
1
  import { useEffect, useState } from 'react'
2
2
 
3
- export function useQueryString () {
3
+ export function useQueryString() {
4
4
  const getQueryString = () => ({
5
5
  hash: window.location.hash.split('?')[0],
6
- queryString: Object.fromEntries(new URLSearchParams(window.location.hash.split('?')[1]))
6
+ queryString: Object.fromEntries(
7
+ new URLSearchParams(window.location.hash.split('?')[1])
8
+ )
7
9
  })
8
10
 
9
11
  const [queryString, setQueryString] = useState(getQueryString())
@@ -11,7 +13,9 @@ export function useQueryString () {
11
13
  useEffect(() => {
12
14
  window.addEventListener('popstate', () => setQueryString(getQueryString()))
13
15
  return () => {
14
- window.removeEventListener('popstate', () => setQueryString(getQueryString()))
16
+ window.removeEventListener('popstate', () =>
17
+ setQueryString(getQueryString())
18
+ )
15
19
  }
16
20
  }, [])
17
21
 
@@ -2,16 +2,13 @@ import { useQueryString } from './hooks'
2
2
 
3
3
  const env = import.meta.env
4
4
 
5
- async function startViewTransition (fun = () => {}, ref, animation) {
6
- if (!document.startViewTransition) return fun()
5
+ async function startViewTransition(fun = () => {}, ref, animation) {
6
+ if (!document.startViewTransition || env.VITE_VIEW_TRANSITION === 'false')
7
+ return fun()
7
8
 
8
9
  ref.style.viewTransitionName = animation
9
10
  await document.startViewTransition(fun).finished
10
11
  ref.style.viewTransitionName = ''
11
12
  }
12
13
 
13
- export {
14
- env,
15
- useQueryString,
16
- startViewTransition
17
- }
14
+ export { env, useQueryString, startViewTransition }
@@ -42,9 +42,7 @@ export default defineConfig(({ mode }) => {
42
42
 
43
43
  css: {
44
44
  postcss: {
45
- plugins: [
46
- autoprefixer
47
- ]
45
+ plugins: [autoprefixer]
48
46
  }
49
47
  },
50
48
 
@@ -52,18 +50,23 @@ export default defineConfig(({ mode }) => {
52
50
  react(),
53
51
  {
54
52
  name: 'html',
55
- transformIndexHtml (html) {
53
+ transformIndexHtml(html) {
56
54
  let gitHash = ''
57
55
  try {
58
- gitHash = execSync('git rev-parse --short HEAD 2> /dev/null').toString().trim()
59
- } catch (e) { }
56
+ gitHash = execSync('git rev-parse --short HEAD 2> /dev/null')
57
+ .toString()
58
+ .trim()
59
+ } catch (e) {}
60
60
 
61
- return html.replaceAll('%VERSION%', `version=${version}, env=${mode}, release-date=${new Date()}, git-hash=${gitHash}`)
61
+ return html.replaceAll(
62
+ '%VERSION%',
63
+ `version=${version}, env=${mode}, release-date=${new Date()}, git-hash=${gitHash}`
64
+ )
62
65
  }
63
66
  },
64
67
  {
65
68
  name: 'svg',
66
- async transform (src, id) {
69
+ async transform(src, id) {
67
70
  let code = id.split('?')[0]
68
71
  const type = id.split('?')[1]
69
72
 
@@ -83,19 +86,12 @@ export default defineConfig(({ mode }) => {
83
86
 
84
87
  test: {
85
88
  root: './',
86
- watch: false,
87
89
  environment: 'jsdom',
88
- include: ['test/**/*.js', 'test/**/*.jsx'],
89
90
  coverage: {
90
- all: true,
91
91
  reportsDirectory: '.coverage',
92
- include: ['src/**/*.js', 'src/**/*.jsx'],
93
- exclude: [
94
- 'src/index.jsx',
95
- 'src/assets/i18n'
96
- ]
92
+ include: ['src/**/*.{js,jsx}'],
93
+ exclude: ['.coverage', 'src/assets', 'src/index.jsx']
97
94
  }
98
95
  }
99
-
100
96
  }
101
97
  })