@eui/cli 22.0.0-alpha.6 → 22.0.0-alpha.60

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 (46) hide show
  1. package/README.md +357 -88
  2. package/bin/eui-cli.js +26 -0
  3. package/bin/scripts/migrate.js +5 -0
  4. package/lib/app-utils/build.js +26 -0
  5. package/lib/app-utils/migrate.js +610 -0
  6. package/lib/app-utils/serve.js +32 -0
  7. package/lib/build.js +28 -7
  8. package/lib/cli.js +16 -2
  9. package/lib/config.js +10 -1
  10. package/lib/skeletons/_angular/base/mock/app/routes/{index.js → index.cjs} +1 -1
  11. package/lib/skeletons/_angular/base/mock/app/routes/{user_routes.js → user_routes.cjs} +1 -1
  12. package/lib/skeletons/_angular/base/mock/{server.js → server.cjs} +1 -1
  13. package/lib/skeletons/_angular/base/package.json +4 -3
  14. package/lib/skeletons/_angular/base-mobile/package.json +5 -4
  15. package/lib/skeletons/_angular/options/eds/src/app/app.component.html +35 -0
  16. package/lib/skeletons/_angular/options/eds/src/app/app.component.spec.ts +56 -0
  17. package/lib/skeletons/_angular/options/eds/src/app/app.component.ts +44 -0
  18. package/lib/skeletons/_angular/options/eds/src/index.html +21 -0
  19. package/lib/skeletons/_angular/options/pnpm/package.json +98 -48
  20. package/lib/skeletons/_react/base/README.md +65 -0
  21. package/lib/skeletons/_react/base/eslint.config.mjs +17 -0
  22. package/lib/skeletons/_react/base/gitignore_TO_REPLACE +34 -0
  23. package/lib/skeletons/_react/base/index.html +13 -0
  24. package/lib/skeletons/_react/base/mock/app/models/user.cjs +6 -0
  25. package/lib/skeletons/_react/base/mock/app/routes/index.cjs +5 -0
  26. package/lib/skeletons/_react/base/mock/app/routes/user_routes.cjs +44 -0
  27. package/lib/skeletons/_react/base/mock/db/db.json +10 -0
  28. package/lib/skeletons/_react/base/mock/server.cjs +23 -0
  29. package/lib/skeletons/_react/base/package.json +29 -0
  30. package/lib/skeletons/_react/base/public/.gitkeep +0 -0
  31. package/lib/skeletons/_react/base/src/App.tsx +73 -0
  32. package/lib/skeletons/_react/base/src/main.tsx +30 -0
  33. package/lib/skeletons/_react/base/src/pages/about.tsx +27 -0
  34. package/lib/skeletons/_react/base/src/pages/home.tsx +50 -0
  35. package/lib/skeletons/_react/base/src/routes.ts +18 -0
  36. package/lib/skeletons/_react/base/src/styles.css +37 -0
  37. package/lib/skeletons/_react/base/src/vite-env.d.ts +1 -0
  38. package/lib/skeletons/_react/base/tsconfig.app.json +18 -0
  39. package/lib/skeletons/_react/base/tsconfig.json +7 -0
  40. package/lib/skeletons/_react/base/tsconfig.node.json +15 -0
  41. package/lib/skeletons/_react/base/vite.config.ts +77 -0
  42. package/lib/skeletons/_react/options/pnpm/package.json +46 -0
  43. package/lib/utils.js +26 -2
  44. package/package.json +1 -1
  45. package/sonar-project.properties +0 -14
  46. /package/lib/skeletons/_angular/base/mock/app/models/{user.js → user.cjs} +0 -0
package/lib/build.js CHANGED
@@ -5,11 +5,7 @@ const utils = require('./utils');
5
5
  const config = require('./config');
6
6
 
7
7
  module.exports.start = (options) => {
8
- try {
9
- build(options.config, options.targetPath)
10
- } catch (e) {
11
- throw e;
12
- }
8
+ build(options.config, options.targetPath);
13
9
  }
14
10
 
15
11
  const build = (cliConfig, targetPath) => {
@@ -33,6 +29,14 @@ const build = (cliConfig, targetPath) => {
33
29
  copyAngular(angularPath, cliConfig, true);
34
30
  }
35
31
 
32
+ // BUILD REACT
33
+ if (appType === 'react') {
34
+ console.log('---building react');
35
+ const reactPath = utils.getAngularPath(targetPath, appName, appType, artifactId);
36
+ console.log(reactPath);
37
+ copyReact(reactPath, cliConfig);
38
+ }
39
+
36
40
  // BUILD web-maven
37
41
  if (appType === 'web-maven') {
38
42
  console.log('--building web-maven');
@@ -63,12 +67,29 @@ const copyAngular = (targetPath, cliConfig, overwrite = true) => {
63
67
  utils.copydir(config.angularBaseMobilePath, targetPath, overwrite);
64
68
  }
65
69
 
66
- if (cliConfig.appOptions === 'ecl') {
70
+ // appOptions may be a plain string (interactive mode) or an array (automated `--config`
71
+ // parses `appOptions` on `_`, e.g. `ecl_something` -> ['ecl', ...]). Normalize to an array.
72
+ const appOptions = [].concat(cliConfig.appOptions || []);
73
+
74
+ if (appOptions.includes('ecl')) {
67
75
  console.log(`eUI ECL theme selected : ` + cliConfig.appOptionsEclTheme);
68
76
  utils.copydir(config.optionsPath[cliConfig.appOptionsEclTheme], targetPath, true);
69
77
  }
70
78
 
79
+ if (appOptions.includes('eds')) {
80
+ console.log(`eUI EDS desktop app-shell selected`);
81
+ utils.copydir(config.edsOptionPath, targetPath, true);
82
+ }
83
+
84
+ if (cliConfig.packageManager === 'pnpm') {
85
+ utils.copy(path.join(config.pnpmOptionPath.angular, 'package.json'), path.join(targetPath, 'package.json'));
86
+ }
87
+ }
88
+
89
+ const copyReact = (targetPath, cliConfig) => {
90
+ utils.copydir(config.reactBasePath, targetPath, true);
91
+
71
92
  if (cliConfig.packageManager === 'pnpm') {
72
- utils.copy(path.join(config.pnpmOptionPath, 'package.json'), path.join(targetPath, 'package.json'));
93
+ utils.copy(path.join(config.pnpmOptionPath.react, 'package.json'), path.join(targetPath, 'package.json'));
73
94
  }
74
95
  }
package/lib/cli.js CHANGED
@@ -50,9 +50,11 @@ module.exports.start = async (options) => {
50
50
 
51
51
  const appTypePrompt = new Select({
52
52
  name: 'appType',
53
- message: 'Select an eUI Angular application type :',
53
+ message: 'Select an eUI application type :',
54
54
  choices: [
55
55
  'Desktop',
56
+ 'Desktop EDS',
57
+ 'React EDS',
56
58
  'Mobile Ionic',
57
59
  'eUI + Spring Boot web module - JDK + Maven required !!!',
58
60
  'eUI + Maven web module (JEE Spring maven web module) - JDK + Maven required !!!'
@@ -64,12 +66,22 @@ module.exports.start = async (options) => {
64
66
  // Map display name to value
65
67
  const appTypeMap = {
66
68
  'Desktop': 'angular',
69
+ 'Desktop EDS': 'angular',
70
+ 'React EDS': 'react',
67
71
  'Mobile Ionic': 'mobile',
68
72
  'eUI + Spring Boot web module - JDK + Maven required !!!': 'web-spring-boot',
69
73
  'eUI + Maven web module (JEE Spring maven web module) - JDK + Maven required !!!': 'web-maven'
70
74
  };
71
75
  answers.appType = appTypeMap[appTypeChoice];
72
76
 
77
+ // "Desktop EDS" is an Angular desktop app whose shell is composed with @eui/eds (eds-shell +
78
+ // EDS components) instead of the legacy @eui/components app-shell. It pre-selects the `eds`
79
+ // app-shell option, so the ECL/default app-shell prompt below is skipped for it.
80
+ const isEdsDesktop = appTypeChoice === 'Desktop EDS';
81
+ if (isEdsDesktop) {
82
+ answers.appOptions = 'eds';
83
+ }
84
+
73
85
  if (answers.appType === 'web-spring-boot') {
74
86
  const groupIdPrompt = new Input({
75
87
  name: 'groupId',
@@ -88,7 +100,9 @@ module.exports.start = async (options) => {
88
100
  answers.artifactId = await artifactIdPrompt.run();
89
101
  }
90
102
 
91
- if (answers.appType !== 'mobile') {
103
+ // ECL app-shell options apply to the Angular-based types only (not mobile, not react, and
104
+ // not when the EDS desktop shell was already chosen up-front).
105
+ if (answers.appType !== 'mobile' && answers.appType !== 'react' && !isEdsDesktop) {
92
106
  const appOptionsPrompt = new Select({
93
107
  name: 'appOptions',
94
108
  message: 'Select one or more additional configuration options :',
package/lib/config.js CHANGED
@@ -9,6 +9,8 @@ module.exports.skeletonsPath = skeletonsPath;
9
9
  module.exports.angularBasePath = path.join(skeletonsPath, '_angular/base');
10
10
  module.exports.angularBaseMobilePath = path.join(skeletonsPath, '_angular/base-mobile');
11
11
 
12
+ module.exports.reactBasePath = path.join(skeletonsPath, '_react/base');
13
+
12
14
  module.exports.webMavenPath = path.join(skeletonsPath, 'web-maven');
13
15
  module.exports.webSpringBootPath = path.join(skeletonsPath, 'web-spring-boot');
14
16
 
@@ -19,7 +21,14 @@ module.exports.optionsPath = {
19
21
  "ecl-ec": path.join(skeletonsPath, '_angular/options/ecl-ec'),
20
22
  "ecl-eu": path.join(skeletonsPath, '_angular/options/ecl-eu'),
21
23
  };
22
- module.exports.pnpmOptionPath = path.join(skeletonsPath, '_angular/options/pnpm');
24
+ // pnpm package.json overlays, keyed by the app stack (Angular vs React). The pnpm variant lists
25
+ // all dependencies explicitly (no @eui/deps-* meta-package) since pnpm is stricter about
26
+ // hoisting; each stack needs its own set.
27
+ module.exports.pnpmOptionPath = {
28
+ angular: path.join(skeletonsPath, '_angular/options/pnpm'),
29
+ react: path.join(skeletonsPath, '_react/options/pnpm'),
30
+ };
31
+ module.exports.edsOptionPath = path.join(skeletonsPath, '_angular/options/eds');
23
32
 
24
33
  module.exports.version = version;
25
34
 
@@ -1,4 +1,4 @@
1
- const userRoutes = require('./user_routes');
1
+ const userRoutes = require('./user_routes.cjs');
2
2
 
3
3
  module.exports = function (app, db) {
4
4
  userRoutes(app, db);
@@ -1,4 +1,4 @@
1
- const User = require('../models/user');
1
+ const User = require('../models/user.cjs');
2
2
  const uuid = require('uuid');
3
3
 
4
4
  module.exports = function (app, db) {
@@ -16,7 +16,7 @@ app.use(bodyParser.urlencoded({ extended: true }));
16
16
  // credentials: true,
17
17
  // }));
18
18
 
19
- require('./app/routes')(app, db);
19
+ require('./app/routes/index.cjs')(app, db);
20
20
 
21
21
  app.listen(port, () => {
22
22
  console.log('We are live on ' + port);
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "eui-angular-app",
3
- "version": "22.0.0-alpha.6",
3
+ "version": "22.0.0-alpha.60",
4
4
  "license": "EUPL-1.1",
5
5
  "scripts": {
6
6
  "ng": "ng",
7
- "start-mock-server": "nodemon --watch ./mock ./mock/server.js",
7
+ "start-mock-server": "nodemon --watch ./mock ./mock/server.cjs",
8
8
  "start-serve": "eui-cli serve-app --configuration=proxy-mock --configEnvTarget=mock",
9
9
  "start": "npm-run-all --parallel start-mock-server start-serve",
10
10
  "start-proxy": "eui-cli serve-app --configuration=proxy",
@@ -20,9 +20,10 @@
20
20
  },
21
21
  "private": true,
22
22
  "dependencies": {
23
- "@eui/deps-base": "22.0.0-alpha.6"
23
+ "@eui/deps-base": "22.0.0-alpha.60"
24
24
  },
25
25
  "devDependencies": {
26
+ "@eui/deps-base-dev": "22.0.0-alpha.60",
26
27
  "npm-run-all": "4.1.5",
27
28
  "json-server": "1.0.0-beta.3",
28
29
  "nodemon": "3.1.11",
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "eui-angular-app",
3
- "version": "22.0.0-alpha.6",
3
+ "version": "22.0.0-alpha.60",
4
4
  "license": "EUPL-1.1",
5
5
  "scripts": {
6
6
  "ng": "ng",
7
- "start-mock-server": "nodemon --watch ./mock ./mock/server.js",
7
+ "start-mock-server": "nodemon --watch ./mock ./mock/server.cjs",
8
8
  "start-serve": "eui-cli serve-app --configuration=proxy-mock --configEnvTarget=mock",
9
9
  "start": "npm-run-all --parallel start-mock-server start-serve",
10
10
  "start-proxy": "eui-cli serve-app --configuration=proxy",
@@ -21,8 +21,9 @@
21
21
  "private": true,
22
22
  "dependencies": {
23
23
  "@eui/deps-base-next": "19.3.17",
24
- "@eui/mobile-core": "20.0.2",
25
- "@eui/mobile-styles": "20.0.2"
24
+ "@eui/mobile-core": "22.0.0-alpha.1",
25
+ "@eui/mobile-styles": "22.0.0-alpha.1",
26
+ "@eui/deps-base": "22.0.0-alpha.60"
26
27
  },
27
28
  "resolutions": {
28
29
  "js-yaml": ">=3.13.1",
@@ -0,0 +1,35 @@
1
+ <eds-shell>
2
+ <!-- Toolbar -->
3
+ <eds-shell-toolbar>
4
+ <eds-shell-menu-toggle (menuToggle)="onToggleSidebar()"></eds-shell-menu-toggle>
5
+ <eds-shell-toolbar-logo></eds-shell-toolbar-logo>
6
+ <eds-shell-toolbar-environment>MOCK</eds-shell-toolbar-environment>
7
+ <eds-shell-toolbar-app appName="appName"></eds-shell-toolbar-app>
8
+
9
+ <eds-shell-toolbar-end>
10
+ <button edsIconButton color="brand" icon="bell" ariaLabel="Notifications"></button>
11
+ <button edsIconButton color="brand" icon="gear" ariaLabel="Settings"></button>
12
+ <eds-user-profile
13
+ fullName="John Doe"
14
+ [isShowUserInfos]="false"
15
+ [isShowAvatarInitials]="true">
16
+ <eds-user-profile-menu>
17
+ <eds-user-profile-menu-item>{{ 'eui.my-profile-informations' | translate }}</eds-user-profile-menu-item>
18
+ <eds-user-profile-menu-item>{{ 'eui.sign-out' | translate }}</eds-user-profile-menu-item>
19
+ </eds-user-profile-menu>
20
+ </eds-user-profile>
21
+ </eds-shell-toolbar-end>
22
+ </eds-shell-toolbar>
23
+
24
+ <!-- Sidebar -->
25
+ <eds-shell-sidebar collapseMode="icons">
26
+ <eds-shell-sidebar-nav [items]="sidebarItems" [hasIcons]="true"></eds-shell-sidebar-nav>
27
+ </eds-shell-sidebar>
28
+
29
+ <!-- Main content -->
30
+ <eds-shell-content>
31
+ <router-outlet></router-outlet>
32
+ </eds-shell-content>
33
+
34
+ <eds-shell-footer copyright="© European Union"></eds-shell-footer>
35
+ </eds-shell>
@@ -0,0 +1,56 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { RouterModule } from '@angular/router';
3
+ import { AppComponent } from './app.component';
4
+ import { EDS_SHELL } from '@eui/eds/eds-shell';
5
+ import { routes } from './app.routes';
6
+ import { provideHttpClientTesting } from '@angular/common/http/testing';
7
+ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
8
+ import { AppStarterService } from './app-starter.service';
9
+ import { CONFIG_TOKEN, I18nService, I18nState, translateConfig, UserService } from '@eui/core';
10
+ import { EuiAppConfig } from '@eui/core';
11
+ import { Observable, of } from 'rxjs';
12
+ import { provideTranslateService } from '@ngx-translate/core';
13
+ import { describe, it, beforeEach, expect, vi } from 'vitest';
14
+ // eslint-disable-next-line
15
+ type SpyObj<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? ReturnType<typeof vi.fn> : T[K] };
16
+ describe('AppComponent', () => {
17
+ let component: AppComponent;
18
+ let fixture: ComponentFixture<AppComponent>;
19
+ let userServiceMock: SpyObj<UserService>;
20
+ let i18nServiceMock: SpyObj<I18nService>;
21
+ let configMock: EuiAppConfig;
22
+ beforeEach(async () => {
23
+ type GetStateReturnType<T> = T extends keyof I18nState ? Observable<I18nState[T]> : Observable<I18nState>;
24
+ userServiceMock = { init: vi.fn() } as SpyObj<UserService>;
25
+ i18nServiceMock = {
26
+ init: vi.fn(),
27
+ getState: vi.fn(<K extends keyof I18nState>(key?: K): GetStateReturnType<K> => {
28
+ if (typeof key === 'string') {
29
+ return of({ activeLang: 'en' }[key]) as GetStateReturnType<K>;
30
+ }
31
+ return of({ activeLang: 'en' }) as GetStateReturnType<K>;
32
+ })
33
+ } as SpyObj<I18nService>;
34
+ configMock = {global: {}, modules: {core: {base: 'localhost:3000', userDetails: 'dummy'}}};
35
+ await TestBed.configureTestingModule({
36
+ imports: [
37
+ RouterModule.forRoot(routes),
38
+ ...EDS_SHELL,
39
+ provideTranslateService(translateConfig),
40
+ ],
41
+ providers: [
42
+ provideHttpClient(withInterceptorsFromDi()),
43
+ provideHttpClientTesting(),
44
+ AppStarterService,
45
+ {provide: UserService, useValue: userServiceMock},
46
+ {provide: I18nService, useValue: i18nServiceMock},
47
+ {provide: CONFIG_TOKEN, useValue: configMock},
48
+ ],
49
+ }).compileComponents();
50
+ fixture = TestBed.createComponent(AppComponent);
51
+ component = fixture.componentInstance;
52
+ });
53
+ it('should create the app', () => {
54
+ expect(component).toBeTruthy();
55
+ });
56
+ });
@@ -0,0 +1,44 @@
1
+ import { Component, viewChild } from '@angular/core';
2
+ import { RouterOutlet } from '@angular/router';
3
+ import { TranslatePipe } from '@ngx-translate/core';
4
+ import { EDS_SHELL, EdsShell, EdsMenuItem } from '@eui/eds/eds-shell';
5
+ import { EDS_ICON_BUTTON } from '@eui/eds/eds-icon-button';
6
+ import { EDS_USER_PROFILE } from '@eui/eds/eds-user-profile';
7
+
8
+ /**
9
+ * Desktop EDS application shell. Mirrors the default Angular desktop skeleton (same routes,
10
+ * features, config and interceptors) but composes the layout with the modern `@eui/eds`
11
+ * `eds-shell` and EDS components instead of the legacy `@eui/components` `eui-app`.
12
+ *
13
+ * The sidebar nav items carry a `url` that the `eds-menu` resolves through Angular's router
14
+ * (`[routerLink]`), so navigation is declarative — no manual `navigate()` call is needed.
15
+ */
16
+ @Component({
17
+ selector: 'app-root',
18
+ templateUrl: './app.component.html',
19
+ imports: [
20
+ RouterOutlet,
21
+ TranslatePipe,
22
+ ...EDS_SHELL,
23
+ ...EDS_ICON_BUTTON,
24
+ ...EDS_USER_PROFILE,
25
+ ],
26
+ })
27
+ export class AppComponent {
28
+ private shell = viewChild.required(EdsShell);
29
+
30
+ sidebarItems: EdsMenuItem[] = [
31
+ { label: 'Home', url: 'screen/home', icon: 'house' },
32
+ {
33
+ label: 'Module 1', url: 'screen/module1', icon: 'stack', children: [
34
+ { label: 'page 1', url: 'screen/module1/page1' },
35
+ { label: 'page 2', url: 'screen/module1/page2' },
36
+ ],
37
+ },
38
+ { label: 'Module 2', url: 'screen/module2', icon: 'folder' },
39
+ ];
40
+
41
+ onToggleSidebar(): void {
42
+ this.shell().toggleSidebar();
43
+ }
44
+ }
@@ -0,0 +1,21 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Application name</title>
6
+ <base href="/">
7
+
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
10
+ </head>
11
+
12
+ <!-- The `eui-21` scope class is required by EDS styling (it provides the --eds-* tokens). -->
13
+ <body class="eui-21">
14
+ <app-root>
15
+ <div id="loader-wrapper">
16
+ <div id="loader"></div>
17
+ </div>
18
+ </app-root>
19
+ </body>
20
+
21
+ </html>
@@ -1,71 +1,121 @@
1
1
  {
2
2
  "name": "eui-angular-app",
3
- "version": "22.0.0-alpha.6",
3
+ "version": "22.0.0-alpha.60",
4
4
  "license": "EUPL-1.1",
5
5
  "scripts": {
6
6
  "ng": "ng",
7
- "start-mock-server": "nodemon --watch ./mock ./mock/server.js",
8
- "start-serve": "eui-cli serve-app --configuration=proxy-mock",
7
+ "start-mock-server": "nodemon --watch ./mock ./mock/server.cjs",
8
+ "start-serve": "eui-cli serve-app --configuration=proxy-mock --configEnvTarget=mock",
9
9
  "start": "npm-run-all --parallel start-mock-server start-serve",
10
10
  "start-proxy": "eui-cli serve-app --configuration=proxy",
11
11
  "start-local": "eui-cli serve-app",
12
12
  "build": "eui-cli build-app",
13
13
  "build-dev": "eui-cli build-app --configuration=development --configEnvTarget=dev",
14
- "build-prod": "eui-cli build-app --configuration=production-optimized --configEnvTarget=prod --skipLint --skipTest",
15
- "app:inject-config": "eui-cli inject-config-app"
14
+ "build-prod": "eui-cli build-app --configuration=production-optimized --configEnvTarget=prod",
15
+ "build-prod-skip-test": "eui-cli build-app --configuration=production-optimized --configEnvTarget=prod --skipTest",
16
+ "build-prod-stats": "eui-cli build-app --configuration=production-optimized --configEnvTarget=prod",
17
+ "app:build": "eui-cli build-app",
18
+ "app:inject-config": "eui-cli inject-config-app",
19
+ "generate-sprite": "eui-cli generate-sprite"
16
20
  },
17
21
  "private": true,
18
22
  "dependencies": {
19
- "@angular/animations": "21.2.5",
20
- "@angular/common": "21.2.5",
21
- "@angular/compiler": "21.2.5",
22
- "@angular/core": "21.2.5",
23
- "@angular/forms": "21.2.5",
24
- "@angular/platform-browser": "21.2.5",
25
- "@angular/platform-browser-dynamic": "21.2.5",
26
- "@angular/router": "21.2.5",
27
- "@angular/elements": "21.2.5",
28
- "@angular/language-service": "21.2.5",
29
- "@angular/service-worker": "21.2.5",
30
- "@angular/cdk": "21.2.3",
31
- "@angular/material": "21.2.3",
32
- "@angular/material-moment-adapter": "21.2.3",
33
- "@angular-devkit/build-angular": "21.2.3",
23
+ "@angular/animations": "22.2.0",
24
+ "@angular/common": "22.2.0",
25
+ "@angular/compiler": "22.2.0",
26
+ "@angular/core": "22.2.0",
27
+ "@angular/forms": "22.2.0",
28
+ "@angular/platform-browser": "22.2.0",
29
+ "@angular/platform-browser-dynamic": "22.2.0",
30
+ "@angular/router": "22.2.0",
31
+ "@angular/elements": "22.2.0",
32
+ "@angular/service-worker": "22.2.0",
33
+ "@angular/cdk": "22.2.0",
34
+ "@angular/material": "22.2.0",
35
+ "@angular/material-moment-adapter": "22.2.0",
36
+ "@angular/material-luxon-adapter": "22.2.0",
37
+ "luxon": "3.7.2",
34
38
  "rxjs": "7.8.2",
35
39
  "tslib": "2.8.1",
36
- "zone.js": "0.15.1",
37
- "@types/lodash": "4.17.20",
38
- "intl": "1.2.5",
39
- "deepmerge-ts": "7.1.5",
40
- "@ngx-translate/core": "15.0.0",
41
- "@ngx-translate/http-loader": "8.0.0",
42
- "reselect": "5.1.1",
43
- "ngx-mask": "20.0.3",
44
- "hammerjs": "2.0.8",
45
- "pikaday": "1.8.2",
46
- "lodash-es": "4.17.23",
40
+ "zone.js": "0.16.2",
41
+ "deepmerge-ts": "8.0.1",
42
+ "deepmerge": "4.3.1",
43
+ "reselect": "5.2.0",
44
+ "ngx-mask": "22.0.1",
45
+ "@ngx-translate/core": "18.0.0",
46
+ "@ngx-translate/http-loader": "18.0.0",
47
+ "lodash-es": "4.18.1",
47
48
  "localforage": "1.10.0",
48
- "@eui/base": "22.0.0-alpha.6",
49
- "@eui/core": "22.0.0-alpha.6",
50
- "@eui/styles": "22.0.0-alpha.6",
51
- "@eui/components": "22.0.0-alpha.6",
52
- "@eui/ecl": "22.0.0-alpha.6",
53
- "@eui/eds": "22.0.0-alpha.6",
54
- "@eui/eds-styles": "22.0.0-alpha.6"
49
+ "@duetds/date-picker": "1.4.0",
50
+ "embla-carousel": "8.6.0",
51
+ "embla-carousel-reactive-utils": "8.6.0",
52
+ "embla-carousel-angular": "22.0.0",
53
+ "embla-carousel-auto-scroll": "8.6.0",
54
+ "moment": "2.31.0",
55
+ "quill": "2.0.3",
56
+ "quill-delta": "5.1.0",
57
+ "quill-better-table": "1.2.10",
58
+ "apexcharts": "5.16.0",
59
+ "marked": "18.0.5",
60
+ "ngx-markdown": "22.0.0",
61
+ "prismjs": "1.30.0",
62
+ "@stackblitz/sdk": "1.11.1",
63
+ "@eui/base": "22.0.0-alpha.60",
64
+ "@eui/core": "22.0.0-alpha.60",
65
+ "@eui/styles": "22.0.0-alpha.60",
66
+ "@eui/components": "22.0.0-alpha.60",
67
+ "@eui/showcase": "22.0.0-alpha.60",
68
+ "@eui/ecl": "22.0.0-alpha.60",
69
+ "@eui/eds": "22.0.0-alpha.60",
70
+ "@eui/eds-styles": "22.0.0-alpha.60",
71
+ "@eui/eds-wc": "22.0.0-alpha.25",
72
+ "@eui/eds-shared": "22.0.0-alpha.60"
55
73
  },
56
74
  "devDependencies": {
57
- "@angular/compiler-cli": "21.2.5",
58
- "@angular/build": "21.2.3",
59
- "@angular/cli": "21.2.3",
60
- "ng-packagr": "23.0.0-alpha.1",
61
- "@eui/cli": "22.0.0-alpha.6",
62
- "typescript": "~6.0.2",
75
+ "@eui/cli": "22.0.0-alpha.60",
76
+ "@angular/compiler-cli": "22.2.0",
77
+ "@angular/language-service": "22.2.0",
78
+ "@angular/build": "22.2.0",
79
+ "@angular/cli": "22.2.0",
80
+ "ng-packagr": "22.2.2",
81
+ "typescript": "6.0.3",
82
+ "@types/node": "24.13.3",
83
+ "@types/lodash-es": "4.17.12",
84
+ "@types/quill": "2.0.14",
85
+ "ts-node": "10.9.2",
86
+ "eslint": "10.11.0",
87
+ "angular-eslint": "22.5.0",
88
+ "@angular-eslint/builder": "22.5.0",
89
+ "@angular-eslint/eslint-plugin": "22.5.0",
90
+ "@angular-eslint/eslint-plugin-template": "22.5.0",
91
+ "@angular-eslint/schematics": "22.5.0",
92
+ "@angular-eslint/template-parser": "22.5.0",
93
+ "eslint-plugin-prefer-arrow": "1.2.3",
94
+ "eslint-plugin-jsdoc": "63.0.12",
95
+ "eslint-plugin-import": "2.32.0",
96
+ "typescript-eslint": "8.63.0",
97
+ "@typescript-eslint/parser": "8.63.0",
98
+ "@typescript-eslint/eslint-plugin": "8.63.0",
99
+ "@eslint/js": "9.39.1",
100
+ "@eslint/eslintrc": "3.3.5",
101
+ "vitest": "4.1.11",
102
+ "@vitest/ui": "4.1.11",
103
+ "@vitest/coverage-v8": "4.1.11",
104
+ "@vitest/coverage-istanbul": "4.1.11",
105
+ "jsdom": "30.0.1",
106
+ "xhr-mock": "2.5.1",
107
+ "@compodoc/compodoc": "2.0.0",
63
108
  "npm-run-all": "4.1.5",
64
109
  "json-server": "1.0.0-beta.3",
65
- "nodemon": "3.1.10",
110
+ "nodemon": "3.1.11",
66
111
  "lowdb": "1.0.0",
67
- "body-parser": "2.2.0",
68
- "express": "5.1.0",
69
- "uuid": "13.0.0"
112
+ "body-parser": "1.20.3",
113
+ "express": "4.21.2"
114
+ },
115
+ "resolutions": {
116
+ "semver": ">=7.5.2",
117
+ "dompurify": ">=3.2.4",
118
+ "tmp": ">0.2.4",
119
+ "tablesort": "5.6.0"
70
120
  }
71
121
  }
@@ -0,0 +1,65 @@
1
+ # eUI React App
2
+
3
+ A React + Vite starter application built with [`@eui/eds-react`](https://eui.ecdevops.eu) — the
4
+ pure-React port of the EU Design System (EDS) components — and React Router.
5
+
6
+ ## Prerequisites
7
+
8
+ - Node.js `^20.19.0 || ^22.12.0 || >=24.15.0`
9
+ - Yarn 1.x (or pnpm)
10
+
11
+ ## Getting started
12
+
13
+ Install dependencies (done automatically by the eUI CLI when you opt in):
14
+
15
+ ```sh
16
+ yarn
17
+ ```
18
+
19
+ Start the dev server (opens on http://localhost:4200):
20
+
21
+ ```sh
22
+ npm start
23
+ ```
24
+
25
+ ## Available scripts
26
+
27
+ | Script | Description |
28
+ | --- | --- |
29
+ | `npm start` | Start the Vite dev server with HMR |
30
+ | `npm run build` | Type-check and build the production bundle into `dist/` |
31
+ | `npm run preview` | Preview the production build locally |
32
+ | `npm run lint` | Lint the `src` folder with ESLint |
33
+ | `npm run test` | Run unit tests with Vitest |
34
+
35
+ ## Project structure
36
+
37
+ ```
38
+ ├── index.html # App entry; <body class="eui-21"> provides the EDS token scope
39
+ ├── vite.config.ts # Vite config; serves EDS icon sprites under /assets/eds
40
+ ├── tsconfig*.json # TypeScript project references
41
+ ├── eslint.config.mjs # Flat ESLint config (single quotes, TS recommended)
42
+ └── src/
43
+ ├── main.tsx # Mounts <App/> in a HashRouter; loads EDS + component styles
44
+ ├── App.tsx # The EdsShell (toolbar + sidebar + routed content)
45
+ ├── routes.ts # Navigation table (sidebar items)
46
+ ├── styles.css # App-level styles
47
+ └── pages/ # Route pages (home, about)
48
+ ```
49
+
50
+ ## Adding a page
51
+
52
+ 1. Create `src/pages/my-page.tsx` exporting a component.
53
+ 2. Add an entry to `NAV_ITEMS` in `src/routes.ts` (path, label, EDS icon name).
54
+ 3. Add a `<Route>` for it in `src/App.tsx`.
55
+
56
+ ## Styling
57
+
58
+ The EDS design tokens (`--eds-*`) are provided by `@eui/eds-styles` and are available anywhere
59
+ under the `eui-21` scope (set on `<body>`). Prefer the `eds-u-*` utility classes for layout. All
60
+ `@eui/eds-react` component styles are loaded via the combined `@eui/eds-react/styles.css` barrel
61
+ in `main.tsx`; to reduce bundle size you can instead import only the per-component CSS you use.
62
+
63
+ ## License
64
+
65
+ EUPL-1.1
@@ -0,0 +1,17 @@
1
+ import js from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+
4
+ export default tseslint.config(
5
+ { ignores: ['dist', 'node_modules'] },
6
+ {
7
+ files: ['src/**/*.{ts,tsx}'],
8
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
9
+ rules: {
10
+ quotes: ['error', 'single', { avoidEscape: true }],
11
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
12
+ '@typescript-eslint/no-explicit-any': 'warn',
13
+ 'prefer-const': 'error',
14
+ 'no-var': 'error',
15
+ },
16
+ },
17
+ );