@eagami/ui 5.75.0 → 5.77.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagami/ui",
3
- "version": "5.75.0",
3
+ "version": "5.77.0",
4
4
  "description": "Lightweight, accessible, themeable Angular UI component library and icon set built on CSS custom properties",
5
5
  "author": "Michal Wiraszka <michal@eagami.com>",
6
6
  "license": "MIT",
@@ -33,7 +33,13 @@
33
33
  "peerDependencies": {
34
34
  "@angular/common": "^21.0.0 || ^22.0.0",
35
35
  "@angular/core": "^21.0.0 || ^22.0.0",
36
- "@angular/forms": "^21.0.0 || ^22.0.0"
36
+ "@angular/forms": "^21.0.0 || ^22.0.0",
37
+ "@angular/router": "^21.0.0 || ^22.0.0"
38
+ },
39
+ "peerDependenciesMeta": {
40
+ "@angular/router": {
41
+ "optional": true
42
+ }
37
43
  },
38
44
  "dependencies": {},
39
45
  "engines": {
@@ -49,6 +55,10 @@
49
55
  "types": "./types/eagami-ui.d.ts",
50
56
  "default": "./fesm2022/eagami-ui.mjs"
51
57
  },
58
+ "./router": {
59
+ "types": "./types/eagami-ui-router.d.ts",
60
+ "default": "./fesm2022/eagami-ui-router.mjs"
61
+ },
52
62
  "./testing": {
53
63
  "types": "./types/eagami-ui-testing.d.ts",
54
64
  "default": "./fesm2022/eagami-ui-testing.mjs"
@@ -61,6 +71,7 @@
61
71
  "src/styles",
62
72
  "schematics",
63
73
  "testing",
74
+ "router",
64
75
  "README.md"
65
76
  ],
66
77
  "schematics": "./schematics/collection.json"
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/eagami-ui-router.mjs",
3
+ "typings": "../types/eagami-ui-router.d.ts"
4
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schematics": {
3
3
  "ng-add": {
4
- "description": "Set up Eagami UI: register the global stylesheet and fonts in an Angular workspace.",
4
+ "description": "Set up Eagami UI: register the global stylesheet, the fonts, and provideStaleBuildReload() in an Angular workspace.",
5
5
  "factory": "./ng-add/index#ngAdd",
6
6
  "schema": "./ng-add/schema.json"
7
7
  }
@@ -2,10 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ngAdd = ngAdd;
4
4
  const schematics_1 = require("@angular-devkit/schematics");
5
+ const utility_1 = require("@schematics/angular/utility");
5
6
  const workspace_1 = require("@schematics/angular/utility/workspace");
6
7
  const utils_1 = require("./utils");
7
8
  function ngAdd(options) {
8
- return (0, schematics_1.chain)([registerStylesheet(options), registerFonts(options), logNextSteps()]);
9
+ return (0, schematics_1.chain)([
10
+ registerStylesheet(options),
11
+ registerFonts(options),
12
+ registerStaleBuildReload(options),
13
+ logNextSteps(),
14
+ ]);
9
15
  }
10
16
  function registerStylesheet(options) {
11
17
  return (0, workspace_1.updateWorkspace)(workspace => {
@@ -41,9 +47,15 @@ function registerFonts(options) {
41
47
  }
42
48
  };
43
49
  }
50
+ function registerStaleBuildReload(options) {
51
+ return async (tree) => {
52
+ const { name } = findProject(await (0, workspace_1.getWorkspace)(tree), options.project);
53
+ return (0, utility_1.addRootProvider)(name, ({ code, external }) => code `${external('provideStaleBuildReload', '@eagami/ui/router')}()`);
54
+ };
55
+ }
44
56
  function logNextSteps() {
45
57
  return (_tree, context) => {
46
- context.logger.info('Eagami UI is set up: the global stylesheet and fonts are registered.');
58
+ context.logger.info('Eagami UI is set up: the global stylesheet and fonts are registered, and provideStaleBuildReload() reloads a tab left open across a deploy into the new build.');
47
59
  context.logger.info('Optional: call provideEagamiUi() in app.config.ts for a custom brand palette or extra locales.');
48
60
  };
49
61
  }
@@ -11,19 +11,20 @@ $target-size-min: 24px;
11
11
  // transparent, so it reads the same on any surface, however coloured. Pass a full
12
12
  // box-shadow value to draw a halo instead, such as an error ring; box-shadow is
13
13
  // dropped in forced-colors (Windows High Contrast) mode, so a real outline stands
14
- // in for it there.
15
- @mixin focus-ring($ring: null) {
14
+ // in for it there. Pass `$offset` to move the outline's gap, which a negative
15
+ // value turns inward.
16
+ @mixin focus-ring($ring: null, $offset: 2px) {
16
17
  @if $ring {
17
18
  outline: none;
18
19
  box-shadow: $ring;
19
20
  } @else {
20
21
  outline: var(--border-width-medium) solid var(--color-border-focus);
21
- outline-offset: 2px;
22
+ outline-offset: $offset;
22
23
  }
23
24
 
24
25
  @media (forced-colors: active) {
25
26
  outline: 2px solid Highlight;
26
- outline-offset: 2px;
27
+ outline-offset: $offset;
27
28
  }
28
29
  }
29
30
 
@@ -0,0 +1,54 @@
1
+ import { EnvironmentProviders, InjectionToken } from "@angular/core";
2
+ /**
3
+ * How a reload into the current build turned out:
4
+ *
5
+ * - `'recovered'`: the reloaded page opened
6
+ * - `'failed-after-reload'`: the reloaded page failed to open too, so the error is left to surface
7
+ * - `'stayed'`: the visitor chose to stay when the browser asked them to confirm leaving
8
+ */
9
+ type StaleBuildReloadOutcome = 'recovered' | 'failed-after-reload' | 'stayed';
10
+ interface StaleBuildReloadReport {
11
+ outcome: StaleBuildReloadOutcome;
12
+ /** The path that failed to open, without its query or fragment. */
13
+ route: string;
14
+ /** The `version` configured in the build that failed to open the page. */
15
+ fromVersion?: string;
16
+ /** The `version` configured in the build making the report. */
17
+ toVersion?: string;
18
+ }
19
+ interface StaleBuildReloadConfig {
20
+ /** The app's version, carried across the reload so a report names both builds. */
21
+ version?: string;
22
+ /** Called once per reload with how it turned out, for example to log it. */
23
+ onReport?: (report: StaleBuildReloadReport) => void;
24
+ }
25
+ declare const LOAD_PAGE: InjectionToken<(url: string, replace: boolean) => void>;
26
+ /**
27
+ * Whether `error` is a failed page load that `provideStaleBuildReload()` has
28
+ * already answered by reloading. Error reporters can drop it, since the
29
+ * reload's outcome reaches `onReport` instead:
30
+ *
31
+ * ```ts
32
+ * Sentry.init({
33
+ * beforeSend: (event, hint) =>
34
+ * isStaleBuildReloadError(hint.originalException) ? null : event,
35
+ * });
36
+ * ```
37
+ */
38
+ export declare function isStaleBuildReloadError(error: unknown): boolean;
39
+ /**
40
+ * Loads the current build in full when the code of a page being opened fails
41
+ * to load, which is what a tab still running a build that a deploy has since
42
+ * replaced runs into. The reload opens the page the visitor asked for, and
43
+ * stops after one attempt if the new build fails as well.
44
+ *
45
+ * ```ts
46
+ * bootstrapApplication(AppComponent, {
47
+ * providers: [provideRouter(routes), provideStaleBuildReload()],
48
+ * });
49
+ * ```
50
+ *
51
+ * Does nothing during server rendering.
52
+ */
53
+ export declare function provideStaleBuildReload(config?: StaleBuildReloadConfig): EnvironmentProviders;
54
+ export type { StaleBuildReloadConfig, StaleBuildReloadOutcome, StaleBuildReloadReport };
@@ -1967,7 +1967,10 @@ export type ButtonAlign = 'start' | 'center' | 'end';
1967
1967
  * while preserving the rendered width. Chrome is tunable per instance via
1968
1968
  * `--ea-button-padding`, `--ea-button-min-height` and `--ea-button-radius`,
1969
1969
  * which is how an icon-only button comes down to little more than its glyph
1970
- * and how a call-to-action becomes a pill. For navigation, put
1970
+ * and how a call-to-action becomes a pill, and `--ea-button-focus-ring-offset`
1971
+ * moves the focus ring's gap, which a negative length draws inside a button
1972
+ * packed too tightly among others for the ring to fit around it. For
1973
+ * navigation, put
1971
1974
  * `ButtonLinkComponent` on an anchor instead (`<a eaButtonLink href="...">`):
1972
1975
  * it takes the same styling inputs and keeps real link behaviour.
1973
1976
  */