@nexterajs/ui 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +279 -34
  2. package/fesm2022/nexterajs-ui-charts.mjs +1096 -0
  3. package/fesm2022/nexterajs-ui-charts.mjs.map +1 -0
  4. package/fesm2022/nexterajs-ui-core.mjs +652 -12
  5. package/fesm2022/nexterajs-ui-core.mjs.map +1 -1
  6. package/fesm2022/nexterajs-ui-display.mjs +1142 -0
  7. package/fesm2022/nexterajs-ui-display.mjs.map +1 -0
  8. package/fesm2022/nexterajs-ui-dropdowns.mjs +321 -33
  9. package/fesm2022/nexterajs-ui-dropdowns.mjs.map +1 -1
  10. package/fesm2022/nexterajs-ui-file-uploader.mjs +572 -10
  11. package/fesm2022/nexterajs-ui-file-uploader.mjs.map +1 -1
  12. package/fesm2022/nexterajs-ui-forms.mjs +2027 -136
  13. package/fesm2022/nexterajs-ui-forms.mjs.map +1 -1
  14. package/fesm2022/nexterajs-ui-grid.mjs +1222 -188
  15. package/fesm2022/nexterajs-ui-grid.mjs.map +1 -1
  16. package/fesm2022/nexterajs-ui-intl.mjs +103 -11
  17. package/fesm2022/nexterajs-ui-intl.mjs.map +1 -1
  18. package/fesm2022/nexterajs-ui-navigation.mjs +1054 -0
  19. package/fesm2022/nexterajs-ui-navigation.mjs.map +1 -0
  20. package/fesm2022/nexterajs-ui-notify.mjs +46 -44
  21. package/fesm2022/nexterajs-ui-notify.mjs.map +1 -1
  22. package/fesm2022/nexterajs-ui-overlay.mjs +1671 -0
  23. package/fesm2022/nexterajs-ui-overlay.mjs.map +1 -0
  24. package/fesm2022/nexterajs-ui-pivot.mjs +51 -26
  25. package/fesm2022/nexterajs-ui-pivot.mjs.map +1 -1
  26. package/fesm2022/nexterajs-ui-shell.mjs +542 -0
  27. package/fesm2022/nexterajs-ui-shell.mjs.map +1 -0
  28. package/fesm2022/nexterajs-ui-tree-view.mjs +5 -2
  29. package/fesm2022/nexterajs-ui-tree-view.mjs.map +1 -1
  30. package/fesm2022/nexterajs-ui-validation.mjs +42 -11
  31. package/fesm2022/nexterajs-ui-validation.mjs.map +1 -1
  32. package/fesm2022/nexterajs-ui.mjs +5 -0
  33. package/fesm2022/nexterajs-ui.mjs.map +1 -1
  34. package/package.json +33 -2
  35. package/styles/_dropdown.scss +5 -5
  36. package/styles/_editor.scss +52 -17
  37. package/styles/_mixins.scss +1 -1
  38. package/styles/_scrollbar.scss +5 -5
  39. package/styles/_status.scss +21 -0
  40. package/styles/_toast.scss +14 -14
  41. package/styles/_tokens.scss +420 -3
  42. package/styles/_widget.scss +14 -3
  43. package/styles/index.scss +6 -4
  44. package/types/nexterajs-ui-charts.d.ts +446 -0
  45. package/types/nexterajs-ui-core.d.ts +387 -22
  46. package/types/nexterajs-ui-display.d.ts +720 -0
  47. package/types/nexterajs-ui-dropdowns.d.ts +191 -48
  48. package/types/nexterajs-ui-file-uploader.d.ts +236 -7
  49. package/types/nexterajs-ui-forms.d.ts +675 -30
  50. package/types/nexterajs-ui-grid.d.ts +448 -93
  51. package/types/nexterajs-ui-intl.d.ts +39 -4
  52. package/types/nexterajs-ui-navigation.d.ts +531 -0
  53. package/types/nexterajs-ui-notify.d.ts +4 -2
  54. package/types/nexterajs-ui-overlay.d.ts +703 -0
  55. package/types/nexterajs-ui-pivot.d.ts +56 -48
  56. package/types/nexterajs-ui-shell.d.ts +294 -0
  57. package/types/nexterajs-ui-tree-view.d.ts +6 -3
  58. package/types/nexterajs-ui-validation.d.ts +20 -11
  59. package/types/nexterajs-ui.d.ts +5 -0
package/README.md CHANGED
@@ -1,64 +1,309 @@
1
- # NexteraUi
1
+ # @nexterajs/ui
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 22.1.0.
3
+ An Angular 22 component library that replaces DevExtreme: data grid and tree list, pivot grid, editors and pickers,
4
+ dialogs, menus, tabs, an app shell, toasts, and a zero-dependency XLSX writer and reader. Every component is standalone,
5
+ signal-based and OnPush, and every colour, size and string can be changed by the application: colours through
6
+ `--nxe-ui-*` CSS custom properties, strings through a runtime-switchable message bundle (English and Indonesian ship).
4
7
 
5
- ## Code scaffolding
8
+ The package is split into 18 secondary entry points, so an application only bundles what it imports.
6
9
 
7
- Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
10
+ ## Install
8
11
 
9
12
  ```bash
10
- ng generate component component-name
13
+ npm install @nexterajs/ui @angular/cdk @angular/animations luxon
11
14
  ```
12
15
 
13
- For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
16
+ | Peer dependency | Version | Needed for |
17
+ |---|---|---|
18
+ | `@angular/core`, `@angular/common`, `@angular/forms` | `^22.0.0` | everything |
19
+ | `@angular/cdk` | `^22.0.0` | overlays, dialogs, menus, focus traps |
20
+ | `@angular/animations` | `^22.0.0` | shared animation definitions |
21
+ | `luxon` | `^3.0.0` | date box, calendar, date formats |
22
+ | `rxjs` | `^7.8.0` | everything |
23
+ | `@angular/router` | `^22.0.0`, **optional** | `@nexterajs/ui/shell` and `@nexterajs/ui/navigation` |
14
24
 
15
- ```bash
16
- ng generate --help
25
+ `@angular/router` is optional: an application that never imports the shell or navigation entry points does not need
26
+ it. The package root re-exports every entry point, so an application that imports from the bare `@nexterajs/ui` does
27
+ need it installed.
28
+
29
+ ## Register the styles
30
+
31
+ Component look and feel is encapsulated in each component; what has to be global ships as one SCSS bundle,
32
+ `@nexterajs/ui/styles` (`styles/index.scss`). Register it **last** in `angular.json`, under
33
+ `projects.<app>.architect.build.options.styles` (and under `test` if your tests render components):
34
+
35
+ ```json
36
+ "styles": [
37
+ "src/styles.scss",
38
+ "node_modules/@nexterajs/ui/styles/index.scss"
39
+ ]
17
40
  ```
18
41
 
19
- ## Building
42
+ That is all a DevExtreme-era application needs: the bundle and the component sheets carry dx.light's look themselves
43
+ (the widget base and its `#333` text, the grid's structure, cell padding and header, the editor and dropdown chrome), so
44
+ a copy of `dx.light.css` or an extract of it (`dx-compat.css`) can be deleted. Where an app skinned DevExtreme, it sets
45
+ tokens (see Theming) instead of restating selectors. From SCSS, `@use '@nexterajs/ui/styles';` loads the same bundle.
20
46
 
21
- To build the library, run:
47
+ Two optional sheets stay outside the bundle, because each is a port of a third-party stylesheet whose overrides depend on
48
+ load order:
22
49
 
23
- ```bash
24
- ng build nextera-ui
50
+ | File | Required | Holds | Where in the list |
51
+ |---|---|---|---|
52
+ | `styles/index.scss` | always | design tokens, widget base, grid structure, editor and dropdown chrome, icons, drag and badge rules | **last** |
53
+ | `styles/_toast.scss` | if you use `NxeToastService` (`@nexterajs/ui/notify`) | toast container, positions, colours, progress bar | **before** your own stylesheet |
54
+ | `styles/_scrollbar.scss` | only if you use `[nxeScrollbar]` (`@nexterajs/ui/styling`) | hides the native bar, draws the rails | **before** your own stylesheet |
55
+
56
+ **The bundle does not include the toast or scrollbar chrome.** Without `_toast.scss` toasts render with no fixed
57
+ container, position or colours; without `_scrollbar.scss` an `[nxeScrollbar]` element keeps its native scrollbar and
58
+ the rails the directive adds are unstyled. Each file is a value-for-value port of the stylesheet it replaces
59
+ (ngx-toastr's `toastr.css`, `perfect-scrollbar.css`), so register it where that stylesheet used to sit: before your own
60
+ stylesheet, so your overrides of the toast or rail rules (a `width` on `.toast-top-center`) still win on order.
61
+
62
+ `index.scss` goes last so its component chrome lands above any reset you ship. Your token overrides do not depend on
63
+ order (see Theming): the library declares its tokens at `:where(:root)`, which has zero specificity, so a plain
64
+ `:root { }` block in `src/styles.scss` (or any app token file) wins wherever it sits in the list. The toast and
65
+ scrollbar files read the same tokens, with fallbacks, so they need nothing else.
66
+
67
+ ## Use a component
68
+
69
+ Import the standalone component from its entry point:
70
+
71
+ ```ts
72
+ import { Component, signal } from '@angular/core';
73
+ import { NxeButtonComponent, NxeTextBoxComponent } from '@nexterajs/ui/forms';
74
+ import { NxeColumnComponent, NxeDataGridComponent } from '@nexterajs/ui/grid';
75
+
76
+ @Component({
77
+ selector: 'app-orders',
78
+ imports: [NxeButtonComponent, NxeTextBoxComponent, NxeDataGridComponent, NxeColumnComponent],
79
+ template: `
80
+ <nxe-text-box [(value)]="search" placeholder="Search" />
81
+ <nxe-data-grid [dataSource]="orders()">
82
+ <nxe-column dataField="poNumber" caption="PO" />
83
+ <nxe-column dataField="total" caption="Total" dataType="number" />
84
+ </nxe-data-grid>
85
+ <nxe-button type="default" text="Save" (onClick)="save()" />
86
+ `,
87
+ })
88
+ export class OrdersComponent {
89
+ readonly search = signal('');
90
+ readonly orders = signal<Order[]>([]);
91
+ save(): void { /* … */ }
92
+ }
25
93
  ```
26
94
 
27
- This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
95
+ Prefer a specific entry point over the bare `@nexterajs/ui`: it keeps the pivot engine and the XLSX writer out of your
96
+ bundle and out of your dev-server rebuilds.
28
97
 
29
- ### Publishing the Library
98
+ ## Theming
30
99
 
31
- Once the project is built, you can publish your library by following these steps:
100
+ Override `--nxe-ui-*` custom properties from your own `:root`. No build step, no `!important`. The defaults reproduce
101
+ DevExtreme's dx.light, so setting nothing changes nothing.
32
102
 
33
- 1. Navigate to the `dist` directory:
103
+ ```scss
104
+ // src/styles.scss (or an app token file it uses)
105
+ :root {
106
+ --nxe-ui-font-size: 13px;
107
+ --nxe-ui-accent: #005caa; // primary buttons, focus, selection
108
+ --nxe-ui-button-hover-bg-primary: #004d8f; // hover and pressed shades are literals:
109
+ --nxe-ui-button-active-bg-primary: #003d72; // set them whenever you set the fill
110
+ --nxe-ui-button-focus-ring: var(--nxe-ui-focus-ring); // opt in to a visible keyboard focus ring
111
+ }
34
112
 
35
- ```bash
36
- cd dist/nextera-ui
37
- ```
113
+ // Dark theme: the library switches its values under a `.dark` class (on <html> or any ancestor).
114
+ // Restate every token you overrode, or the library's own dark value replaces yours.
115
+ :root.dark {
116
+ --nxe-ui-accent: #4da3e8;
117
+ --nxe-ui-button-hover-bg-primary: #7ab9e8;
118
+ --nxe-ui-button-active-bg-primary: #9acbee;
119
+ }
120
+ ```
38
121
 
39
- 2. Run the `npm publish` command to publish your library to the npm registry:
40
- ```bash
41
- npm publish
42
- ```
122
+ What to know before you theme:
43
123
 
44
- ## Running unit tests
124
+ - **Your `:root` beats the library, in any order.** The library's light defaults are declared at `:where(:root)` and
125
+ its dark values at `:where(.dark)`, both zero specificity.
126
+ - **Restate overrides under `:root.dark`.** A token you set only in `:root` is replaced by the library's dark value as
127
+ soon as `.dark` is on.
128
+ - **Set button hover and active shades explicitly.** `--nxe-ui-button-bg-{primary,success,danger}` follow
129
+ `--nxe-ui-accent`, `--nxe-ui-success` and `--nxe-ui-danger`, but `--nxe-ui-button-hover-bg-*` and
130
+ `--nxe-ui-button-active-bg-*` are fixed colours (dx's shades are not a constant mix), so a new fill keeps the old
131
+ hover and pressed colours until you set them too.
132
+ - **Buttons draw no focus ring by default**, as in DevExtreme. Opt in with
133
+ `--nxe-ui-button-focus-ring: var(--nxe-ui-focus-ring)` (or any `box-shadow` value). Do: a keyboard user otherwise
134
+ cannot see which button has focus.
135
+ - **Accessibility: override the stock danger and success buttons.** The default danger button is white text on
136
+ `#d9534f`, 3.96:1, which fails WCAG AA (4.5:1) for button-sized text; the default success button (white on `#5cb85c`)
137
+ is 2.48:1. For example:
45
138
 
46
- To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command:
139
+ ```scss
140
+ :root {
141
+ --nxe-ui-button-bg-danger: #b4322a; // 6.1:1 with white
142
+ --nxe-ui-button-hover-bg-danger: #9a2a23;
143
+ --nxe-ui-button-active-bg-danger: #7a211b;
144
+ }
145
+ ```
47
146
 
48
- ```bash
49
- ng test
147
+ Do the same for `--nxe-ui-button-bg-success` and its hover and active tokens, and restate them under `:root.dark`.
148
+ - A `nxe-density-compact` class on an ancestor tightens control heights and padding.
149
+
150
+ - **Skin the grid with tokens, not cell selectors.** `--nxe-ui-grid-cell-padding` (dx's 7px),
151
+ `--nxe-ui-grid-cell-vertical-align` (middle), `--nxe-ui-grid-edge-padding` (the first and last cell's outer side),
152
+ `--nxe-ui-grid-header-bg` and `--nxe-ui-grid-header-color` (the caption row), and `--nxe-ui-grid-indicator-scale` /
153
+ `--nxe-ui-grid-indicator-offset` (the sort and filter marks). Set them at `:root`, or on a subtree such as
154
+ `nxe-tree-list` or a card, and they reach every grid inside. The cell rules carry zero specificity, so an existing
155
+ app rule still wins while you move it to a token.
156
+
157
+ The full list of tokens (193, in 22 groups) with light defaults, dark values and what each one colours is in
158
+ `docs/TOKENS.md` in the nextera-library repository. It is generated from `styles/_tokens.scss`, which ships in this
159
+ package (`node_modules/@nexterajs/ui/styles/_tokens.scss`) and carries the same list with a comment on each token.
160
+
161
+ ## Internationalisation
162
+
163
+ Every string the library renders itself (pager, no-data text, filter operators, calendar, validation, uploader, pivot
164
+ captions, shell and dialog labels) comes from `NxeMessageService` in `@nexterajs/ui/core`. English is the default and
165
+ Indonesian (`id`) ships; switching the language re-renders live components in place.
166
+
167
+ ```ts
168
+ import { provideNxeMessages } from '@nexterajs/ui/core';
169
+
170
+ bootstrapApplication(App, {
171
+ providers: [
172
+ provideNxeMessages({
173
+ locale: 'id', // 'en' (default) or 'id'; 'id-ID' picks 'id'
174
+ overrides: { 'grid.noData': 'Belum ada data' }, // kept across language switches
175
+ separators: true, // 1.234,5 under id, 1,234.5 under en
176
+ }),
177
+ ],
178
+ });
50
179
  ```
51
180
 
52
- ## Running end-to-end tests
181
+ ```ts
182
+ import { inject } from '@angular/core';
183
+ import { NxeMessageService } from '@nexterajs/ui/core';
53
184
 
54
- For end-to-end (e2e) testing, run:
185
+ const messages = inject(NxeMessageService);
186
+ messages.use('en'); // switch at runtime
187
+ messages.use({ 'common.cancel': 'Annuler' }, 'fr'); // an ad hoc bundle under a locale
188
+ messages.override({ 'grid.pager.info': 'Hal. {0}/{1}' });
189
+ ```
55
190
 
56
- ```bash
57
- ng e2e
191
+ `provideNxeMessages` also takes `bundles` (more languages; a partial bundle falls back to English) and `luxon` (default
192
+ `true`: Luxon's default locale follows the language, so month and weekday names do too). A component input such as
193
+ `noDataText` always wins over the bundle. To follow an app-owned language service such as Transloco, subscribe to its
194
+ language stream with `takeUntilDestroyed()` and call `messages.use(lang)`. Form-field error messages are set with
195
+ `provideNxeErrorMessages` from `@nexterajs/ui/forms`.
196
+
197
+ ## Entry points
198
+
199
+ | Entry point | Holds |
200
+ |---|---|
201
+ | `@nexterajs/ui/core` | Message service and bundles, default-options token, form-control and config-option base classes, `nxeTemplate` |
202
+ | `@nexterajs/ui/forms` | Button, text box, text area, number box, date box, check box, radio group, switch, OTP box, form field, scroll view |
203
+ | `@nexterajs/ui/dropdowns` | Select box, tag box, drop-down box, list, autocomplete |
204
+ | `@nexterajs/ui/grid` | Data grid and tree list, filter row, header filters, grouping, summaries, master-detail, remote data source, paginator, Excel export |
205
+ | `@nexterajs/ui/pivot` | Pivot grid, its data source, field panel and chooser, chart binding, Excel export |
206
+ | `@nexterajs/ui/display` | Tag, badge, spinner, skeleton, empty state, card, description list |
207
+ | `@nexterajs/ui/charts` | Line, area and donut charts: SVG, light and dark palette tokens, legend, tooltip, data table alternative |
208
+ | `@nexterajs/ui/overlay` | Dialog service, confirmation service, menu |
209
+ | `@nexterajs/ui/navigation` | Tabs, with a router mode (needs `@angular/router`) |
210
+ | `@nexterajs/ui/shell` | App shell, side navigation, top bar (needs `@angular/router`) |
211
+ | `@nexterajs/ui/notify` | Toast service and toast component (register `styles/_toast.scss`) |
212
+ | `@nexterajs/ui/tree-view` | Tree view |
213
+ | `@nexterajs/ui/file-uploader` | File uploader |
214
+ | `@nexterajs/ui/validation` | Validator, validation rules and group, rule evaluators |
215
+ | `@nexterajs/ui/intl` | Date and number format engines, number separator tokens |
216
+ | `@nexterajs/ui/excel` | Zero-dependency XLSX writer and reader, zip, `nxeSaveAs` |
217
+ | `@nexterajs/ui/styling` | Overlay pane helper, `[nxeScrollbar]` (register `styles/_scrollbar.scss`), DevExtreme class-name compatibility |
218
+ | `@nexterajs/ui/animations` | Shared animation definitions |
219
+
220
+ ## Component index
221
+
222
+ Names only. Inputs, outputs, keyboard behaviour and examples are in the full documentation: the `README.md` at the root
223
+ of the nextera-library repository.
224
+
225
+ - **core**: `NxeMessageService`, `provideNxeMessages`, `NXE_MESSAGES_EN`, `NXE_MESSAGES_ID`, `NXE_DEFAULT_OPTIONS`,
226
+ `NxeFormControlBase`, `NxeConfigOptionBase`, `[nxeTemplate]`
227
+ - **forms**: `nxe-button`, `nxe-text-box`, `nxe-text-area`, `nxe-number-box`, `nxe-date-box`, `nxe-check-box`,
228
+ `nxe-radio-group`, `nxe-switch`, `nxe-otp-box`, `nxe-form-field`, `nxe-scroll-view`, `provideNxeErrorMessages`
229
+ - **dropdowns**: `nxe-select-box`, `nxe-tag-box`, `nxe-drop-down-box`, `nxe-list`, `nxe-autocomplete` (with
230
+ `[nxeAutocomplete]` and `nxe-option`), `nxe-auto-complete`
231
+ - **grid**: `nxe-data-grid`, `nxe-tree-list`, `nxe-column`, `nxe-selection`, `nxe-paging`, `nxe-pager`,
232
+ `nxe-filter-row`, `nxe-header-filter`, `nxe-grouping`, `nxe-group-panel`, `nxe-summary`, `nxe-editing`,
233
+ `nxe-master-detail`, `nxe-scrolling`, `nxe-paginator`, `NxeRemoteDataSource`, `nxeFlattenFilter`, `nxeFilterAnd`,
234
+ `nxeFilterOr`, `exportDataGrid`, `exportNxeGridToExcel`
235
+ - **pivot**: `nxe-pivot-grid`, `NxePivotDataSource`, `nxe-pivot-field-panel`, `nxe-pivot-field-chooser`, `nxe-chart`,
236
+ `NxeExcelExportService`
237
+ - **display**: `nxe-tag`, `nxe-badge` (with `[nxeBadgeAnchor]`), `nxe-spinner`, `nxe-skeleton`, `nxe-empty-state`,
238
+ `nxe-card`, `nxe-description-list`, `nxe-description-item`
239
+ - **overlay**: `NxeDialogService`, `NxeDialogRef`, `NxeConfirmService`, `[nxe-dialog-title]`, `[nxe-dialog-content]`,
240
+ `[nxe-dialog-actions]`, `nxe-menu`, `[nxeMenuTriggerFor]`, `nxe-menu-item` / `[nxe-menu-item]`, `nxe-menu-divider`
241
+ - **navigation**: `nxe-tabs`, `nxe-tab`, `ng-template[nxeTabContent]`
242
+ - **shell**: `nxe-shell`, `nxe-sidenav`, `nxe-topbar`, `ng-template[nxeSidenavIcon]`
243
+ - **notify**: `NxeToastService`, `provideNxeToast`, `nxe-toast`
244
+ - **tree-view**: `nxe-tree-view`
245
+ - **file-uploader**: `nxe-file-uploader`
246
+ - **validation**: `nxe-validator`, `nxe-validation-rule`, `nxe-validation-group`, `NxeValidators`
247
+ - **intl**: `formatNumber`, `parseNumber`, `formatDisplay`, `parseDisplay`, `NXE_NUMBER_SEPARATORS`,
248
+ `NXE_ID_SEPARATORS`
249
+ - **excel**: `NxeWorkbook`, `NxeWorksheet`, `readXlsxFirstSheet`, `nxeSaveAs`
250
+ - **styling**: `[nxeScrollbar]`, `nxePane`, `provideNxeDxCompat`
251
+ - **animations**: `nxeAnimations`, `NxeAnimationCurves`, `NxeAnimationDurations`
252
+
253
+ ## Consuming a local build (`file:` or `npm link`)
254
+
255
+ To try an unreleased build, point the application at the built package (`npm run build:ui` in the library repository
256
+ writes `dist/nextera-ui`):
257
+
258
+ ```json
259
+ "dependencies": { "@nexterajs/ui": "file:../nextera-library/dist/nextera-ui" }
58
260
  ```
59
261
 
60
- Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
262
+ npm installs a `file:` directory dependency (and `npm link`) as a symlink. Followed to its real path, the library
263
+ resolves `@angular/core` from the library repository's own `node_modules`, so the application ends up with two copies
264
+ of Angular: `NG0203` (`inject()` called outside an injection context) at runtime, or `INPUT_SIGNAL_BRAND` type errors
265
+ in the editor. Three settings keep the library on the application's copy:
266
+
267
+ 1. `angular.json`, the build target's options:
268
+
269
+ ```json
270
+ "build": { "options": { "preserveSymlinks": true } }
271
+ ```
272
+
273
+ 2. `tsconfig.json`, `compilerOptions`:
274
+
275
+ ```json
276
+ "preserveSymlinks": true
277
+ ```
278
+
279
+ 3. Unit tests with `@angular/build:unit-test` (Vitest). Vitest loads dependencies with Node's own resolver, which
280
+ follows the symlink regardless, so inline the package to route its imports through Vite. Turn on the runner config
281
+ in `angular.json`:
282
+
283
+ ```json
284
+ "test": { "builder": "@angular/build:unit-test", "options": { "runnerConfig": true } }
285
+ ```
286
+
287
+ and add `vitest-base.config.mjs` next to `angular.json` (the file `runnerConfig: true` looks for):
288
+
289
+ ```js
290
+ import { defineConfig } from 'vitest/config';
291
+
292
+ export default defineConfig({
293
+ test: {
294
+ server: { deps: { inline: [/@nexterajs\/ui/] } },
295
+ },
296
+ });
297
+ ```
298
+
299
+ Remove all three when you switch back to a published version.
300
+
301
+ ## Browser support
302
+
303
+ The browsers Angular 22 supports. The stylesheets use `color-mix()`, `:where()`, `:has()`, container queries and
304
+ `dvh` units, which puts the floor at Chrome and Edge 111, Firefox 121 and Safari 16.4. Internet Explorer and legacy
305
+ Edge are not supported.
61
306
 
62
- ## Additional Resources
307
+ ## License
63
308
 
64
- For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
309
+ Apache-2.0. See `LICENSE` and `NOTICE` in this package.