@atlasauth/angular 0.1.2 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, PLATFORM_ID, computed, Injectable, TemplateRef, ViewContainerRef, Directive, Input, ElementRef, Renderer2, RendererStyleFlags2, EventEmitter, Output, ChangeDetectionStrategy, Component, signal, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule } from '@angular/core';
3
- import { isPlatformBrowser } from '@angular/common';
2
+ import { InjectionToken, inject, PLATFORM_ID, computed, Injectable, TemplateRef, ViewContainerRef, Directive, Input, ElementRef, Renderer2, EventEmitter, Output, ChangeDetectionStrategy, Component, signal, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule } from '@angular/core';
3
+ import { isPlatformBrowser, DOCUMENT } from '@angular/common';
4
4
  import { toSignal } from '@angular/core/rxjs-interop';
5
5
  import { BehaviorSubject, combineLatest, firstValueFrom } from 'rxjs';
6
6
  import { map, distinctUntilChanged, filter, take } from 'rxjs/operators';
@@ -8,6 +8,8 @@ import { TokenCache, FapiClient, getProviderToken, readRedirectResult, stripRedi
8
8
  export { FapiClient, advance, flowFromPending, getProviderToken, initialFlow, pollAttempt, prepareFactor, requestForStep, shouldKeepPolling } from '@atlasauth/js';
9
9
  import { evaluate } from '@atlasauth/authz';
10
10
  export { evaluate, hasFromClaims } from '@atlasauth/authz';
11
+ import { renderDesignAppearance, instanceDesignFrom, applyAppearanceToDom } from '@atlasauth/design/runtime';
12
+ export { instanceDesignFrom } from '@atlasauth/design/runtime';
11
13
  import { Router } from '@angular/router';
12
14
 
13
15
  /**
@@ -108,6 +110,39 @@ function classFor(element, appearance, base) {
108
110
  const override = appearance?.elements?.[element];
109
111
  return override ? `${base} ${override}` : base;
110
112
  }
113
+ // ---- the design system ---------------------------------------------------------
114
+ /**
115
+ * The legacy tokens the developer chose EXPLICITLY: a non-default `baseTheme`
116
+ * plus `variables`. Only these map onto a design — the token defaults must not
117
+ * overwrite the dashboard design.
118
+ */
119
+ function explicitTokens(appearance) {
120
+ const out = {};
121
+ if (appearance?.baseTheme && appearance.baseTheme !== 'default') {
122
+ Object.assign(out, THEMES[appearance.baseTheme]);
123
+ }
124
+ for (const [key, value] of Object.entries(appearance?.variables ?? {})) {
125
+ if (value !== undefined)
126
+ out[key] = value;
127
+ }
128
+ return out;
129
+ }
130
+ /**
131
+ * Turn an `appearance` (+ the instance's dashboard design from the Frontend
132
+ * API) into root attributes and a stylesheet — the same semantics as
133
+ * `@atlasauth/react`. Precedence, lowest first: dashboard design < `preset` <
134
+ * `variables` (and a non-default `baseTheme`) < `design`. Without a dashboard
135
+ * design and without `preset`/`design`, the output is exactly the
136
+ * pre-design-system one: the token variables, no stylesheet, no attributes.
137
+ */
138
+ function renderAppearance(appearance, instanceDesign, options = {}) {
139
+ return renderDesignAppearance(appearance, instanceDesign, {
140
+ tokens: explicitTokens(appearance),
141
+ legacyStyle: () => cssVariables(resolveTokens(appearance)),
142
+ frontendApi: options.frontendApi,
143
+ warn: options.warn,
144
+ });
145
+ }
111
146
 
112
147
  /**
113
148
  * §10.3: "Every string passes through an i18n catalog; en-US ships, catalog
@@ -304,6 +339,33 @@ class AtlasService {
304
339
  appearanceVariables() {
305
340
  return cssVariables(resolveTokens(this.options.appearance));
306
341
  }
342
+ /**
343
+ * The full appearance render for a root element: inline variables, the
344
+ * `data-atlas-*` attributes and the design stylesheet. Pass the dashboard
345
+ * design (from {@link loadInstanceDesign}) to layer code overrides on it —
346
+ * the same semantics as `@atlasauth/react`.
347
+ */
348
+ appearanceRender(instanceDesign) {
349
+ return renderAppearance(this.options.appearance, instanceDesign ?? null, {
350
+ frontendApi: this.baseUrl,
351
+ });
352
+ }
353
+ /**
354
+ * The design configured in the Atlas dashboard (`GET /v1/appearance`), or null
355
+ * when there is none, it cannot be read, or the app opted out with
356
+ * `appearance.instanceDesign: false`.
357
+ */
358
+ async loadInstanceDesign() {
359
+ if (this.options.appearance?.instanceDesign === false)
360
+ return null;
361
+ try {
362
+ const response = await this.call('/v1/appearance');
363
+ return response.ok ? instanceDesignFrom(await response.json()) : null;
364
+ }
365
+ catch {
366
+ return null;
367
+ }
368
+ }
307
369
  /** A fresh {@link FapiClient} for driving a sign-in/sign-up flow. */
308
370
  createFapiClient() {
309
371
  return new FapiClient({ publishableKey: this.publishableKey, baseUrl: this.baseUrl });
@@ -722,18 +784,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
722
784
  * <router-outlet></router-outlet>
723
785
  * </div>
724
786
  * ```
787
+ *
788
+ * With a design (a code-level `appearance.preset` / `appearance.design`, or
789
+ * the dashboard design, fetched in the browser) the host also gets the stable
790
+ * `data-atlas-*` attributes and the design stylesheet is added to `<head>` once.
725
791
  */
726
792
  class AtlasRootDirective {
727
793
  atlas = inject(AtlasService);
728
794
  el = inject(ElementRef);
729
795
  renderer = inject(Renderer2);
796
+ document = inject(DOCUMENT);
797
+ platformId = inject(PLATFORM_ID);
730
798
  ngOnInit() {
731
- this.renderer.addClass(this.el.nativeElement, 'atlas-root');
732
- const vars = this.atlas.appearanceVariables();
733
- for (const [name, value] of Object.entries(vars)) {
734
- // DashCase so a `--atlas-*` custom property is written verbatim, not camelCased.
735
- this.renderer.setStyle(this.el.nativeElement, name, value, RendererStyleFlags2.DashCase);
736
- }
799
+ const host = this.el.nativeElement;
800
+ this.renderer.addClass(host, 'atlas-root');
801
+ // Custom properties via `style.setProperty` (written verbatim, never camelCased).
802
+ let applied = applyAppearanceToDom(this.document, host, this.atlas.appearanceRender());
803
+ if (!isPlatformBrowser(this.platformId))
804
+ return;
805
+ void this.atlas.loadInstanceDesign().then((design) => {
806
+ if (!design)
807
+ return;
808
+ applied = applyAppearanceToDom(this.document, host, this.atlas.appearanceRender(design), applied);
809
+ });
737
810
  }
738
811
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
739
812
  static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: AtlasRootDirective, isStandalone: true, selector: "[atlasRoot]", ngImport: i0 });
@@ -1553,5 +1626,5 @@ function atlasChildGuard(options = {}) {
1553
1626
  * Generated bundle index. Do not edit.
1554
1627
  */
1555
1628
 
1556
- export { ATLAS_OPTIONS, ATLAS_UI, AtlasFlowController, AtlasLoadedDirective, AtlasLoadingDirective, AtlasModule, AtlasProtectDirective, AtlasRootDirective, AtlasService, AtlasSignedInDirective, AtlasSignedOutDirective, AttemptFlowComponent, DEFAULT_TOKENS, EN_US, OrganizationProfileComponent, OrganizationSwitcherComponent, SignInComponent, SignUpComponent, THEMES, UserButtonComponent, UserProfileComponent, atlasChildGuard, atlasGuard, classFor, cssVariables, provideAtlas, resolveTokens, translate, withFallback };
1629
+ export { ATLAS_OPTIONS, ATLAS_UI, AtlasFlowController, AtlasLoadedDirective, AtlasLoadingDirective, AtlasModule, AtlasProtectDirective, AtlasRootDirective, AtlasService, AtlasSignedInDirective, AtlasSignedOutDirective, AttemptFlowComponent, DEFAULT_TOKENS, EN_US, OrganizationProfileComponent, OrganizationSwitcherComponent, SignInComponent, SignUpComponent, THEMES, UserButtonComponent, UserProfileComponent, atlasChildGuard, atlasGuard, classFor, cssVariables, explicitTokens, provideAtlas, renderAppearance, resolveTokens, translate, withFallback };
1557
1630
  //# sourceMappingURL=atlasauth-angular.mjs.map