@hitachivantara/uikit-cli 6.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/README.md +46 -0
- package/package.json +68 -0
- package/src/app-shell.js +106 -0
- package/src/baselines/app-shell/vite/_gitignore +30 -0
- package/src/baselines/app-shell/vite/_oxlintrc.json +5 -0
- package/src/baselines/app-shell/vite/_package.json +55 -0
- package/src/baselines/app-shell/vite/public/locales/en/example.json +8 -0
- package/src/baselines/app-shell/vite/src/lib/data/config.ts +15 -0
- package/src/baselines/app-shell/vite/src/lib/i18n.ts +44 -0
- package/src/baselines/app-shell/vite/src/pages/Example/index.tsx +25 -0
- package/src/baselines/app-shell/vite/src/providers/Provider.tsx +31 -0
- package/src/baselines/app-shell/vite/src/tests/mocks.ts +1 -0
- package/src/baselines/app-shell/vite/src/tests/providers.tsx +13 -0
- package/src/baselines/app-shell/vite/src/tests/setupTests.ts +24 -0
- package/src/baselines/app-shell/vite/src/types/theme.d.ts +8 -0
- package/src/baselines/app-shell/vite/src/types/vite-env.d.ts +1 -0
- package/src/baselines/app-shell/vite/tsconfig.json +10 -0
- package/src/baselines/app-shell/vite/tsconfig.node.json +9 -0
- package/src/baselines/app-shell/vite/uno.config.ts +6 -0
- package/src/baselines/app-shell/vite/vite.config.ts +45 -0
- package/src/baselines/vite/_gitignore +30 -0
- package/src/baselines/vite/_oxlintrc.json +5 -0
- package/src/baselines/vite/_package.json +53 -0
- package/src/baselines/vite/index.html +18 -0
- package/src/baselines/vite/public/favicon.ico +0 -0
- package/src/baselines/vite/public/locales/en/common.json +16 -0
- package/src/baselines/vite/public/locales/en/home.json +4 -0
- package/src/baselines/vite/public/logo192.png +0 -0
- package/src/baselines/vite/src/App.tsx +31 -0
- package/src/baselines/vite/src/assets/HitachiLogo.tsx +27 -0
- package/src/baselines/vite/src/components/common/Loading/Loading.test.tsx +18 -0
- package/src/baselines/vite/src/components/common/Loading/Loading.tsx +15 -0
- package/src/baselines/vite/src/components/common/Loading/index.ts +1 -0
- package/src/baselines/vite/src/context/NavigationContext.tsx +67 -0
- package/src/baselines/vite/src/lib/i18n.ts +29 -0
- package/src/baselines/vite/src/main.tsx +12 -0
- package/src/baselines/vite/src/pages/Home/index.tsx +13 -0
- package/src/baselines/vite/src/pages/NotFound/NotFound.tsx +39 -0
- package/src/baselines/vite/src/pages/NotFound/index.tsx +1 -0
- package/src/baselines/vite/src/pages/layout/navigation.tsx +82 -0
- package/src/baselines/vite/src/routes.tsx +14 -0
- package/src/baselines/vite/src/tests/mocks.ts +1 -0
- package/src/baselines/vite/src/tests/providers.tsx +13 -0
- package/src/baselines/vite/src/tests/setupTests.ts +24 -0
- package/src/baselines/vite/src/types/theme.d.ts +8 -0
- package/src/baselines/vite/src/vite-env.d.ts +1 -0
- package/src/baselines/vite/tsconfig.json +10 -0
- package/src/baselines/vite/tsconfig.node.json +9 -0
- package/src/baselines/vite/uno.config.ts +6 -0
- package/src/baselines/vite/vite.config.ts +31 -0
- package/src/contents.js +63 -0
- package/src/create.js +172 -0
- package/src/index.js +22 -0
- package/src/navigation.js +21 -0
- package/src/package.js +37 -0
- package/src/plop-templates/README.md.hbs +10 -0
- package/src/plop-templates/app-shell/app-shell.config.ts.hbs +54 -0
- package/src/plop-templates/app-shell/index.html.hbs +15 -0
- package/src/plopfile.js +61 -0
- package/src/templates/AssetInventory/CardView.tsx +167 -0
- package/src/templates/AssetInventory/ListView.tsx +56 -0
- package/src/templates/AssetInventory/data.tsx +255 -0
- package/src/templates/AssetInventory/index.tsx +198 -0
- package/src/templates/AssetInventory/usePaginationData.ts +158 -0
- package/src/templates/Canvas/Context.tsx +49 -0
- package/src/templates/Canvas/ListView.tsx +189 -0
- package/src/templates/Canvas/Node.tsx +203 -0
- package/src/templates/Canvas/Sidebar.tsx +51 -0
- package/src/templates/Canvas/StatusEdge.tsx +75 -0
- package/src/templates/Canvas/StickyNode.tsx +475 -0
- package/src/templates/Canvas/Table.tsx +202 -0
- package/src/templates/Canvas/TreeView.tsx +211 -0
- package/src/templates/Canvas/dependencies.json +7 -0
- package/src/templates/Canvas/index.tsx +363 -0
- package/src/templates/Canvas/styles.tsx +41 -0
- package/src/templates/Canvas/utils.tsx +70 -0
- package/src/templates/Dashboard/GridPanel.tsx +33 -0
- package/src/templates/Dashboard/Kpi.tsx +107 -0
- package/src/templates/Dashboard/Map.styles.ts +681 -0
- package/src/templates/Dashboard/Map.tsx +71 -0
- package/src/templates/Dashboard/data.ts +67 -0
- package/src/templates/Dashboard/dependencies.json +11 -0
- package/src/templates/Dashboard/index.tsx +173 -0
- package/src/templates/DetailsView/KPIs.tsx +70 -0
- package/src/templates/DetailsView/MetadataItem.tsx +35 -0
- package/src/templates/DetailsView/Properties.tsx +127 -0
- package/src/templates/DetailsView/Table.tsx +104 -0
- package/src/templates/DetailsView/data.ts +67 -0
- package/src/templates/DetailsView/index.tsx +102 -0
- package/src/templates/DetailsView/usePaginationData.ts +155 -0
- package/src/templates/DetailsView/utils.ts +51 -0
- package/src/templates/Form/index.tsx +107 -0
- package/src/templates/KanbanBoard/ColumnContainer.tsx +89 -0
- package/src/templates/KanbanBoard/TaskCard.tsx +130 -0
- package/src/templates/KanbanBoard/data.tsx +140 -0
- package/src/templates/KanbanBoard/dependencies.json +6 -0
- package/src/templates/KanbanBoard/index.tsx +179 -0
- package/src/templates/KanbanBoard/styles.tsx +76 -0
- package/src/templates/KanbanBoard/types.ts +21 -0
- package/src/templates/ListView/Indicator.tsx +42 -0
- package/src/templates/ListView/Kpi.tsx +120 -0
- package/src/templates/ListView/Table.tsx +55 -0
- package/src/templates/ListView/data.tsx +179 -0
- package/src/templates/ListView/dependencies.json +5 -0
- package/src/templates/ListView/index.tsx +245 -0
- package/src/templates/ListView/usePaginationData.ts +158 -0
- package/src/templates/Welcome/index.tsx +101 -0
- package/src/templates/package.json +30 -0
- package/src/utils.js +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Hitachi Vantara UI Kit CLI
|
|
2
|
+
|
|
3
|
+
The Hitachi Vantara CLI for UI Kit apps.
|
|
4
|
+
|
|
5
|
+
This CLI provides a way to automate tasks you regularly perform as part of your development workflow.
|
|
6
|
+
|
|
7
|
+
Whether is quickly start a new application or scaffolding out templates and components, it will help you standardize these tasks in a consistent, and predictable manner.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
For usage documentation, run the CLI with the `--help` option for any `<command>`. Examples:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npx @hitachivantara/uikit-cli@latest --help
|
|
15
|
+
npx @hitachivantara/uikit-cli@latest <command> --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Creating an App
|
|
19
|
+
|
|
20
|
+
You can create a new app using the different baselines provided and our official supported templates.
|
|
21
|
+
|
|
22
|
+
To get started, use the following command:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npx @hitachivantara/uikit-cli@latest create
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
It launches an interactive experience that guides you through setting up a new app.
|
|
29
|
+
|
|
30
|
+
You can also directly specify the app name and the template to use. For example:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npx @hitachivantara/uikit-cli@latest create MyAppName --templates Form
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## How to test
|
|
37
|
+
|
|
38
|
+
You can run the project locally by executing the following command:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
node <path-to-repo>/uikit-cli/src/index.js create
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
This project is licensed under the terms of the [Apache 2.0 license](/LICENSE.md).
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hitachivantara/uikit-cli",
|
|
3
|
+
"version": "6.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"author": "Hitachi Vantara UI Kit Team",
|
|
7
|
+
"description": "The Hitachi Vantara CLI for UI Kit apps.",
|
|
8
|
+
"homepage": "https://github.com/pentaho/hv-uikit-react",
|
|
9
|
+
"license": "Apache-2.0",
|
|
10
|
+
"main": "src/index.js",
|
|
11
|
+
"bin": {
|
|
12
|
+
"uikit-cli": "src/index.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"hitachivantara",
|
|
16
|
+
"uikit-cli",
|
|
17
|
+
"cli"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/pentaho/hv-uikit-react.git",
|
|
22
|
+
"directory": "packages/cli"
|
|
23
|
+
},
|
|
24
|
+
"bugs": {
|
|
25
|
+
"url": "https://github.com/pentaho/hv-uikit-react/issues"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"clean": "npx rimraf package",
|
|
29
|
+
"prepare": "npx cpy ../../templates src",
|
|
30
|
+
"pretest": "node src/index.js create uikit-app -t Form,ListView",
|
|
31
|
+
"test": "cd uikit-app",
|
|
32
|
+
"posttest": "npx rimraf uikit-app",
|
|
33
|
+
"prepublishOnly": "npm run clean && npx clean-publish"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"chalk": "^5.2.0",
|
|
37
|
+
"colors": "^1.4.0",
|
|
38
|
+
"commander": "^10.0.0",
|
|
39
|
+
"fs-extra": "^11.1.0",
|
|
40
|
+
"inquirer": "^9.1.4",
|
|
41
|
+
"node-plop": "^0.31.1"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/fs-extra": "^11.0.1",
|
|
45
|
+
"cpy-cli": "^5.0.0",
|
|
46
|
+
"i18next": "^24.2.2",
|
|
47
|
+
"i18next-browser-languagedetector": "^8.0.3",
|
|
48
|
+
"i18next-http-backend": "^3.0.2",
|
|
49
|
+
"react-i18next": "15.7.1",
|
|
50
|
+
"react-router-dom": "^6.29.0",
|
|
51
|
+
"vite-tsconfig-paths": "^5.1.0"
|
|
52
|
+
},
|
|
53
|
+
"engineStrict": true,
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=16"
|
|
56
|
+
},
|
|
57
|
+
"files": [
|
|
58
|
+
"src"
|
|
59
|
+
],
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public",
|
|
62
|
+
"directory": "package"
|
|
63
|
+
},
|
|
64
|
+
"clean-publish": {
|
|
65
|
+
"withoutPublish": true,
|
|
66
|
+
"tempDir": "package"
|
|
67
|
+
}
|
|
68
|
+
}
|
package/src/app-shell.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import nodePlop from "node-plop";
|
|
4
|
+
|
|
5
|
+
import { __dirname } from "./utils.js";
|
|
6
|
+
|
|
7
|
+
const plop = await nodePlop(`${__dirname}/plopfile.js`);
|
|
8
|
+
|
|
9
|
+
const createAppShellIndexHtml = plop.getGenerator("createAppShellIndexHtml");
|
|
10
|
+
const createAppShellConfig = plop.getGenerator("createAppShellConfig");
|
|
11
|
+
const createAppShellAutoMenu = plop.getGenerator("createAppShellAutoMenu");
|
|
12
|
+
|
|
13
|
+
const createAppShellIndexHtmlFile = async (path, name) => {
|
|
14
|
+
await createAppShellIndexHtml.runActions({
|
|
15
|
+
path,
|
|
16
|
+
appName: name.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const createAppShellConfigFile = async (
|
|
21
|
+
path,
|
|
22
|
+
name,
|
|
23
|
+
appShellFeatures = [],
|
|
24
|
+
appShellAutoMenu = true,
|
|
25
|
+
) => {
|
|
26
|
+
const pagesPath = `${path}/src/pages`;
|
|
27
|
+
const pages = fs.readdirSync(pagesPath);
|
|
28
|
+
|
|
29
|
+
const templatePages = pages.map((page) => ({
|
|
30
|
+
path,
|
|
31
|
+
pagesPath: "pages",
|
|
32
|
+
name: page,
|
|
33
|
+
pageName: page.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
const appShellFeatMap = {
|
|
37
|
+
AppSwitcher: {
|
|
38
|
+
bundle: "@hv/app-switcher-client/toggle.js",
|
|
39
|
+
config:
|
|
40
|
+
'{ title: "Apps",\n\t\t\t\t\t\t\t\t\tapps: [\n\t\t\t\t\t\t\t\t\t\t{ label: "App 1", description: "Application 1", url: "#", target: "NEW" },\n\t\t\t\t\t\t\t\t\t\t{ label: "App 2", description: "Application 2", url: "#", target: "SELF", icon: { iconType: "uikit", name: "Warehouse" } }\n\t\t\t\t\t\t\t\t\t]}',
|
|
41
|
+
},
|
|
42
|
+
ColorModeSwitcher: {
|
|
43
|
+
bundle: "@hv/theming-client/colorModeSwitcher.js",
|
|
44
|
+
},
|
|
45
|
+
HelpLink: {
|
|
46
|
+
bundle: "@hv/help-client/button.js",
|
|
47
|
+
config:
|
|
48
|
+
'{ url: "https://www.hitachivantara.com/", description: "Hitachi Vantara Help Link" }',
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const appShellFeats = appShellFeatures
|
|
53
|
+
.map((feat) => appShellFeatMap[feat])
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
|
|
56
|
+
await createAppShellConfig.runActions({
|
|
57
|
+
path,
|
|
58
|
+
appName: name.replace(/([a-z])([A-Z])/g, "$1 $2"),
|
|
59
|
+
pages: templatePages,
|
|
60
|
+
feats: appShellFeats,
|
|
61
|
+
appShellAutoMenu,
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export const createAppShellBaseline = async (appPath) => {
|
|
66
|
+
const basePath = `${__dirname}/baselines/app-shell/vite`;
|
|
67
|
+
|
|
68
|
+
console.log(`\nCreating a new App Shell app in\n${chalk.green(appPath)}\n`);
|
|
69
|
+
|
|
70
|
+
// copy baseline contents
|
|
71
|
+
fs.copySync(basePath, appPath, { overwrite: true });
|
|
72
|
+
fs.moveSync(`${appPath}/_gitignore`, `${appPath}/.gitignore`);
|
|
73
|
+
fs.moveSync(`${appPath}/_package.json`, `${appPath}/package.json`);
|
|
74
|
+
fs.moveSync(`${appPath}/_oxlintrc.json`, `${appPath}/.oxlintrc.json`);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const setupAppShell = async (
|
|
78
|
+
appPath,
|
|
79
|
+
name,
|
|
80
|
+
appShellFeatures = [],
|
|
81
|
+
appShellAutoMenu = true,
|
|
82
|
+
packageName,
|
|
83
|
+
) => {
|
|
84
|
+
console.log(`\nConfiguring App Shell environment\n`);
|
|
85
|
+
|
|
86
|
+
// use our index.html (without favicon and similar stuff)
|
|
87
|
+
await createAppShellIndexHtmlFile(appPath, name);
|
|
88
|
+
|
|
89
|
+
// generate app shell config file
|
|
90
|
+
await createAppShellConfigFile(
|
|
91
|
+
appPath,
|
|
92
|
+
name,
|
|
93
|
+
appShellFeatures,
|
|
94
|
+
appShellAutoMenu,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (appShellAutoMenu) {
|
|
98
|
+
await createAppShellAutoMenu.runActions({ path: appPath });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// replace package name in i18n.ts file
|
|
102
|
+
const i18nFile = `${appPath}/src/lib/i18n.ts`;
|
|
103
|
+
const i18nData = fs.readFileSync(i18nFile, { encoding: "utf-8" });
|
|
104
|
+
const i18nUpdated = i18nData.replace("uikit-app", packageName);
|
|
105
|
+
fs.writeFileSync(i18nFile, i18nUpdated);
|
|
106
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
pnpm-debug.log*
|
|
8
|
+
lerna-debug.log*
|
|
9
|
+
|
|
10
|
+
node_modules
|
|
11
|
+
build
|
|
12
|
+
dist
|
|
13
|
+
dist-ssr
|
|
14
|
+
*.local
|
|
15
|
+
.env
|
|
16
|
+
.npm
|
|
17
|
+
.eslintcache
|
|
18
|
+
*.tgz
|
|
19
|
+
coverage
|
|
20
|
+
|
|
21
|
+
# Editor directories and files
|
|
22
|
+
.vscode/*
|
|
23
|
+
!.vscode/extensions.json
|
|
24
|
+
.idea
|
|
25
|
+
.DS_Store
|
|
26
|
+
*.suo
|
|
27
|
+
*.ntvs*
|
|
28
|
+
*.njsproj
|
|
29
|
+
*.sln
|
|
30
|
+
*.sw?
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hv-apps/uikit-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview",
|
|
9
|
+
"check": "npm run check:format && npm run check:types && npm run check:lint",
|
|
10
|
+
"check:types": "tsc --noEmit",
|
|
11
|
+
"check:lint": "oxlint",
|
|
12
|
+
"check:format": "prettier --check .",
|
|
13
|
+
"lint": "oxlint --fix",
|
|
14
|
+
"format": "prettier --write .",
|
|
15
|
+
"test": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"prettier": "@hitachivantara/uikit-config/prettier",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@emotion/css": "^11.10.6",
|
|
20
|
+
"@emotion/react": "^11.10.6",
|
|
21
|
+
"@emotion/styled": "^11.10.6",
|
|
22
|
+
"@hitachivantara/uikit-react-core": "^6.0.0-next.0",
|
|
23
|
+
"@hitachivantara/uikit-react-icons": "^6.0.0-next.0",
|
|
24
|
+
"@mui/material": "^7.0.2",
|
|
25
|
+
"i18next": "^23.7.8",
|
|
26
|
+
"i18next-browser-languagedetector": "^7.0.1",
|
|
27
|
+
"i18next-http-backend": "^2.1.1",
|
|
28
|
+
"react": "^18.2.0",
|
|
29
|
+
"react-dom": "^18.2.0",
|
|
30
|
+
"react-i18next": "^14.0.0",
|
|
31
|
+
"react-router-dom": "^6.14.2",
|
|
32
|
+
"swr": "^2.2.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@hitachivantara/app-shell-vite-plugin": "^2.0.0-next.0",
|
|
36
|
+
"@hitachivantara/uikit-config": "^0.5.1",
|
|
37
|
+
"@hitachivantara/uikit-uno-preset": "^1.0.0-next.0",
|
|
38
|
+
"@testing-library/jest-dom": "^6.1.5",
|
|
39
|
+
"@testing-library/react": "^14.0.0",
|
|
40
|
+
"@testing-library/user-event": "^14.4.3",
|
|
41
|
+
"@types/react": "^18.0.28",
|
|
42
|
+
"@types/react-dom": "^18.0.11",
|
|
43
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
44
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
45
|
+
"happy-dom": "^15.11.7",
|
|
46
|
+
"oxlint": "^1.9.0",
|
|
47
|
+
"prettier": "^3.1.1",
|
|
48
|
+
"typescript": "^5.5.4",
|
|
49
|
+
"unocss": "^66.4.2",
|
|
50
|
+
"vite": "^7.1.1",
|
|
51
|
+
"vite-plugin-css-injected-by-js": "^3.3.1",
|
|
52
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
53
|
+
"vitest": "^3.2.4"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import baseUseSWR, { Key, SWRConfiguration } from "swr";
|
|
2
|
+
|
|
3
|
+
const fetcher = (url: RequestInfo | URL) =>
|
|
4
|
+
fetch(url).then((res) => res.json());
|
|
5
|
+
|
|
6
|
+
// overload the useSWR function to set the fetcher and add suspense by default
|
|
7
|
+
export default function useSWR<Data, Error = unknown>(
|
|
8
|
+
key: Key,
|
|
9
|
+
options?: SWRConfiguration<Data, Error>,
|
|
10
|
+
) {
|
|
11
|
+
return baseUseSWR<Data, Error>(key, fetcher, {
|
|
12
|
+
suspense: true,
|
|
13
|
+
...options,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { initReactI18next } from "react-i18next";
|
|
3
|
+
import { createInstance, type i18n } from "i18next";
|
|
4
|
+
import LanguageDetector from "i18next-browser-languagedetector";
|
|
5
|
+
import Backend, { type HttpBackendOptions } from "i18next-http-backend";
|
|
6
|
+
|
|
7
|
+
const initAppI18n = (baseUrl: string) => {
|
|
8
|
+
const i18nInstance: i18n = createInstance();
|
|
9
|
+
|
|
10
|
+
const loadPath = `${baseUrl}locales/{{lng}}/{{ns}}.json`;
|
|
11
|
+
|
|
12
|
+
i18nInstance
|
|
13
|
+
// load translation using xhr -> see /public/locales
|
|
14
|
+
// learn more: https://github.com/i18next/i18next-xhr-backend
|
|
15
|
+
.use(Backend)
|
|
16
|
+
// detect user language
|
|
17
|
+
// learn more: https://github.com/i18next/i18next-browser-languageDetector
|
|
18
|
+
.use(LanguageDetector)
|
|
19
|
+
// pass the i18n instance to react-i18next.
|
|
20
|
+
.use(initReactI18next)
|
|
21
|
+
// init i18next
|
|
22
|
+
// for all options read: https://www.i18next.com/overview/configuration-options
|
|
23
|
+
.init<HttpBackendOptions>({
|
|
24
|
+
fallbackLng: "en",
|
|
25
|
+
supportedLngs: ["en"],
|
|
26
|
+
backend: {
|
|
27
|
+
loadPath,
|
|
28
|
+
},
|
|
29
|
+
interpolation: {
|
|
30
|
+
escapeValue: false, // not needed for react as it escapes by default
|
|
31
|
+
},
|
|
32
|
+
load: "languageOnly",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return i18nInstance;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const useI18nInstance = () => {
|
|
39
|
+
const moduleId = "@hv-apps/uikit-app";
|
|
40
|
+
return useMemo(
|
|
41
|
+
() => initAppI18n(import.meta.resolve?.(`${moduleId}/`) || ""),
|
|
42
|
+
[moduleId],
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useTranslation } from "react-i18next";
|
|
2
|
+
import {
|
|
3
|
+
HvGlobalActions,
|
|
4
|
+
HvGrid,
|
|
5
|
+
HvTypography,
|
|
6
|
+
} from "@hitachivantara/uikit-react-core";
|
|
7
|
+
|
|
8
|
+
import { withProvider } from "../../providers/Provider";
|
|
9
|
+
|
|
10
|
+
const Example = () => {
|
|
11
|
+
const { t } = useTranslation("example");
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<HvGrid container>
|
|
15
|
+
<HvGrid item xs={12}>
|
|
16
|
+
<HvTypography variant="title2">{t("page.title")}</HvTypography>
|
|
17
|
+
</HvGrid>
|
|
18
|
+
<HvGrid item xs={12}>
|
|
19
|
+
<HvGlobalActions title={t("section.title")} variant="section" />
|
|
20
|
+
</HvGrid>
|
|
21
|
+
</HvGrid>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default withProvider(Example);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Suspense } from "react";
|
|
2
|
+
import { I18nextProvider } from "react-i18next";
|
|
3
|
+
|
|
4
|
+
import { useI18nInstance } from "../lib/i18n";
|
|
5
|
+
|
|
6
|
+
const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
7
|
+
const i18n = useI18nInstance();
|
|
8
|
+
|
|
9
|
+
return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function withProvider<
|
|
13
|
+
P extends Record<string, unknown> = Record<string, unknown>,
|
|
14
|
+
>(WrappedComponent: React.ComponentType<P>) {
|
|
15
|
+
const ComponentWithProvider: React.FC<P> = (props) => {
|
|
16
|
+
return (
|
|
17
|
+
<Provider>
|
|
18
|
+
<Suspense fallback={null}>
|
|
19
|
+
<WrappedComponent {...props} />
|
|
20
|
+
</Suspense>
|
|
21
|
+
</Provider>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const displayName = WrappedComponent.displayName || WrappedComponent.name;
|
|
26
|
+
ComponentWithProvider.displayName = `withProvider(${displayName})`;
|
|
27
|
+
|
|
28
|
+
return ComponentWithProvider;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default Provider;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SUSPENSE_LABEL = "LOADING";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FC, ReactNode, Suspense } from "react";
|
|
2
|
+
import { HvProvider } from "@hitachivantara/uikit-react-core";
|
|
3
|
+
|
|
4
|
+
import { SUSPENSE_LABEL } from "./mocks";
|
|
5
|
+
|
|
6
|
+
/** Base Test Provider */
|
|
7
|
+
export const TestProvider: FC<{ children: ReactNode }> = ({ children }) => {
|
|
8
|
+
return (
|
|
9
|
+
<Suspense fallback={SUSPENSE_LABEL}>
|
|
10
|
+
<HvProvider>{children}</HvProvider>
|
|
11
|
+
</Suspense>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TransProps } from "react-i18next";
|
|
2
|
+
import type { ThirdPartyModule, TOptionsBase } from "i18next";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
import "@testing-library/jest-dom";
|
|
6
|
+
|
|
7
|
+
vi.mock("react-i18next", async () => {
|
|
8
|
+
const { initReactI18next } = await vi.importActual<{
|
|
9
|
+
initReactI18next: ThirdPartyModule;
|
|
10
|
+
}>("react-i18next");
|
|
11
|
+
|
|
12
|
+
const t = (str: string, options?: TOptionsBase) =>
|
|
13
|
+
options?.returnObjects ? undefined : str;
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
initReactI18next,
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
+
Trans: ({ i18nKey }: TransProps<any>) => i18nKey,
|
|
19
|
+
useTranslation: () => ({
|
|
20
|
+
t,
|
|
21
|
+
i18n: { changeLanguage: async () => t },
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Theme } from "@mui/material/styles";
|
|
2
|
+
|
|
3
|
+
// makeStyles is now exported from @mui/styles package which does not know about Theme
|
|
4
|
+
// we need to augment the DefaultTheme (empty object) in @mui/styles with Theme from the core.
|
|
5
|
+
declare module "@mui/private-theming" {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
7
|
+
interface DefaultTheme extends Theme {}
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
/// <reference types="vitest" />
|
|
3
|
+
|
|
4
|
+
import react from "@vitejs/plugin-react";
|
|
5
|
+
import unoCSS from "unocss/vite";
|
|
6
|
+
import { defineConfig } from "vite";
|
|
7
|
+
import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
|
|
8
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
9
|
+
import { HvAppShellVitePlugin } from "@hitachivantara/app-shell-vite-plugin";
|
|
10
|
+
|
|
11
|
+
export default defineConfig(({ mode }) => ({
|
|
12
|
+
plugins: [
|
|
13
|
+
react(),
|
|
14
|
+
tsconfigPaths(),
|
|
15
|
+
unoCSS({ mode: "per-module" }),
|
|
16
|
+
cssInjectedByJsPlugin({
|
|
17
|
+
relativeCSSInjection: true,
|
|
18
|
+
}),
|
|
19
|
+
HvAppShellVitePlugin({
|
|
20
|
+
mode,
|
|
21
|
+
autoViewsAndRoutes: true,
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
test: {
|
|
26
|
+
globals: true,
|
|
27
|
+
environment: "happy-dom",
|
|
28
|
+
setupFiles: ["src/tests/setupTests.ts"],
|
|
29
|
+
reporters: "default",
|
|
30
|
+
coverage: {
|
|
31
|
+
enabled: false, // disabled by default. run vitest with --coverage
|
|
32
|
+
provider: "v8",
|
|
33
|
+
reporter: "lcov",
|
|
34
|
+
include: ["src/**/*.ts?(x)"],
|
|
35
|
+
exclude: [
|
|
36
|
+
"src/**/mocks/*",
|
|
37
|
+
"src/**/tests/*",
|
|
38
|
+
"src/**/*.test.ts?(x)",
|
|
39
|
+
"src/**/styles.[jt]s?(x)",
|
|
40
|
+
"src/**/*.d.ts",
|
|
41
|
+
"src/*.tsx",
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
}));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Logs
|
|
2
|
+
logs
|
|
3
|
+
*.log
|
|
4
|
+
npm-debug.log*
|
|
5
|
+
yarn-debug.log*
|
|
6
|
+
yarn-error.log*
|
|
7
|
+
pnpm-debug.log*
|
|
8
|
+
lerna-debug.log*
|
|
9
|
+
|
|
10
|
+
node_modules
|
|
11
|
+
build
|
|
12
|
+
dist
|
|
13
|
+
dist-ssr
|
|
14
|
+
*.local
|
|
15
|
+
.env
|
|
16
|
+
.npm
|
|
17
|
+
.eslintcache
|
|
18
|
+
*.tgz
|
|
19
|
+
coverage
|
|
20
|
+
|
|
21
|
+
# Editor directories and files
|
|
22
|
+
.vscode/*
|
|
23
|
+
!.vscode/extensions.json
|
|
24
|
+
.idea
|
|
25
|
+
.DS_Store
|
|
26
|
+
*.suo
|
|
27
|
+
*.ntvs*
|
|
28
|
+
*.njsproj
|
|
29
|
+
*.sln
|
|
30
|
+
*.sw?
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "uikit-app",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview",
|
|
9
|
+
"check": "npm run check:format && npm run check:types && npm run check:lint",
|
|
10
|
+
"check:types": "tsc --noEmit",
|
|
11
|
+
"check:lint": "oxlint",
|
|
12
|
+
"check:format": "prettier --check .",
|
|
13
|
+
"lint": "oxlint --fix",
|
|
14
|
+
"format": "prettier --write .",
|
|
15
|
+
"test": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"prettier": "@hitachivantara/uikit-config/prettier",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@emotion/css": "^11.10.6",
|
|
20
|
+
"@emotion/react": "^11.10.6",
|
|
21
|
+
"@emotion/styled": "^11.10.6",
|
|
22
|
+
"@hitachivantara/uikit-react-core": "^6.0.0-next.0",
|
|
23
|
+
"@hitachivantara/uikit-react-icons": "^6.0.0-next.0",
|
|
24
|
+
"@mui/material": "^7.0.2",
|
|
25
|
+
"i18next": "^22.4.10",
|
|
26
|
+
"i18next-browser-languagedetector": "^7.0.1",
|
|
27
|
+
"i18next-http-backend": "^2.1.1",
|
|
28
|
+
"react": "^18.2.0",
|
|
29
|
+
"react-dom": "^18.2.0",
|
|
30
|
+
"react-i18next": "^12.2.0",
|
|
31
|
+
"react-router-dom": "^6.8.2",
|
|
32
|
+
"tiny-cookie": "^2.4.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@hitachivantara/uikit-config": "^0.5.1",
|
|
36
|
+
"@hitachivantara/uikit-uno-preset": "^1.0.0-next.0",
|
|
37
|
+
"@testing-library/jest-dom": "^6.1.5",
|
|
38
|
+
"@testing-library/react": "^14.0.0",
|
|
39
|
+
"@testing-library/user-event": "^14.4.3",
|
|
40
|
+
"@types/react": "^18.0.28",
|
|
41
|
+
"@types/react-dom": "^18.0.11",
|
|
42
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
43
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
44
|
+
"happy-dom": "^15.11.7",
|
|
45
|
+
"oxlint": "^1.9.0",
|
|
46
|
+
"prettier": "^3.1.1",
|
|
47
|
+
"typescript": "^5.5.4",
|
|
48
|
+
"unocss": "^66.4.2",
|
|
49
|
+
"vite": "^7.1.1",
|
|
50
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
51
|
+
"vitest": "^3.2.4"
|
|
52
|
+
}
|
|
53
|
+
}
|