@atlasauth/angular 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.
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/LICENSE +21 -0
- package/dist/README.md +195 -0
- package/dist/esm2022/atlasauth-angular.mjs +5 -0
- package/dist/esm2022/lib/appearance.mjs +92 -0
- package/dist/esm2022/lib/atlas.config.mjs +8 -0
- package/dist/esm2022/lib/atlas.service.mjs +329 -0
- package/dist/esm2022/lib/atlas.ui.mjs +36 -0
- package/dist/esm2022/lib/components/attempt-flow.component.mjs +180 -0
- package/dist/esm2022/lib/components/flow-controller.mjs +88 -0
- package/dist/esm2022/lib/components/organization-profile.component.mjs +56 -0
- package/dist/esm2022/lib/components/organization-switcher.component.mjs +63 -0
- package/dist/esm2022/lib/components/sign-in.component.mjs +59 -0
- package/dist/esm2022/lib/components/sign-up.component.mjs +54 -0
- package/dist/esm2022/lib/components/user-button.component.mjs +94 -0
- package/dist/esm2022/lib/components/user-profile.component.mjs +81 -0
- package/dist/esm2022/lib/directives/atlas-root.directive.mjs +42 -0
- package/dist/esm2022/lib/directives/loaded.directive.mjs +23 -0
- package/dist/esm2022/lib/directives/loading.directive.mjs +23 -0
- package/dist/esm2022/lib/directives/protect.directive.mjs +82 -0
- package/dist/esm2022/lib/directives/signed-in.directive.mjs +29 -0
- package/dist/esm2022/lib/directives/signed-out.directive.mjs +29 -0
- package/dist/esm2022/lib/directives/toggle.directive.mjs +42 -0
- package/dist/esm2022/lib/fapi.mjs +9 -0
- package/dist/esm2022/lib/guards/atlas.guard.mjs +54 -0
- package/dist/esm2022/lib/i18n.mjs +78 -0
- package/dist/esm2022/lib/protect.mjs +9 -0
- package/dist/esm2022/lib/provide-atlas.mjs +85 -0
- package/dist/esm2022/lib/types.mjs +6 -0
- package/dist/esm2022/public-api.mjs +35 -0
- package/dist/fesm2022/atlasauth-angular.mjs +1557 -0
- package/dist/fesm2022/atlasauth-angular.mjs.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/lib/appearance.d.ts +85 -0
- package/dist/lib/atlas.config.d.ts +31 -0
- package/dist/lib/atlas.service.d.ts +127 -0
- package/dist/lib/atlas.ui.d.ts +22 -0
- package/dist/lib/components/attempt-flow.component.d.ts +48 -0
- package/dist/lib/components/flow-controller.d.ts +34 -0
- package/dist/lib/components/organization-profile.component.d.ts +16 -0
- package/dist/lib/components/organization-switcher.component.d.ts +15 -0
- package/dist/lib/components/sign-in.component.d.ts +21 -0
- package/dist/lib/components/sign-up.component.d.ts +21 -0
- package/dist/lib/components/user-button.component.d.ts +19 -0
- package/dist/lib/components/user-profile.component.d.ts +15 -0
- package/dist/lib/directives/atlas-root.directive.d.ts +26 -0
- package/dist/lib/directives/loaded.directive.d.ts +13 -0
- package/dist/lib/directives/loading.directive.d.ts +12 -0
- package/dist/lib/directives/protect.directive.d.ts +41 -0
- package/dist/lib/directives/signed-in.directive.d.ts +17 -0
- package/dist/lib/directives/signed-out.directive.d.ts +17 -0
- package/dist/lib/directives/toggle.directive.d.ts +25 -0
- package/dist/lib/fapi.d.ts +8 -0
- package/dist/lib/guards/atlas.guard.d.ts +43 -0
- package/dist/lib/i18n.d.ts +23 -0
- package/dist/lib/protect.d.ts +8 -0
- package/dist/lib/provide-atlas.d.ts +46 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/public-api.d.ts +28 -0
- package/package.json +58 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { signal } from '@angular/core';
|
|
2
|
+
import { advance, flowFromPending, initialFlow, pollAttempt, shouldKeepPolling, } from '@atlasauth/js';
|
|
3
|
+
/**
|
|
4
|
+
* The server-driven sign-in / sign-up engine, shared by `<atlas-sign-in>` and
|
|
5
|
+
* `<atlas-sign-up>` — the Angular counterpart of React's `useFlow` hook.
|
|
6
|
+
*
|
|
7
|
+
* It owns no decision about what comes next: every status comes back from the
|
|
8
|
+
* server via `advance`, and this controller only posts whatever the current step
|
|
9
|
+
* needs and re-renders the returned status. State lives in a signal so templates
|
|
10
|
+
* update whether the app runs zoned or zoneless.
|
|
11
|
+
*/
|
|
12
|
+
export class AtlasFlowController {
|
|
13
|
+
client;
|
|
14
|
+
reload;
|
|
15
|
+
state;
|
|
16
|
+
pollTimer = null;
|
|
17
|
+
constructor(client, reload, pending) {
|
|
18
|
+
this.client = client;
|
|
19
|
+
this.reload = reload;
|
|
20
|
+
// Seeded from a redirect that came back mid-flow (e.g. OAuth needing a second
|
|
21
|
+
// factor) so the user resumes at the demanded step instead of starting over.
|
|
22
|
+
this.state = signal(pending ? flowFromPending(pending) : initialFlow);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Advance the flow with the values the user typed. On completion, exchange the
|
|
26
|
+
* one-time ticket for cookies over a same-origin request (FAPI is cross-origin
|
|
27
|
+
* and cannot set the cookie on its own response), then re-boot so the rest of
|
|
28
|
+
* the app sees a signed-in user.
|
|
29
|
+
*/
|
|
30
|
+
async submit(values) {
|
|
31
|
+
this.state.update((current) => ({ ...current, busy: true, errors: [] }));
|
|
32
|
+
const next = await advance(this.client, this.state(), values);
|
|
33
|
+
this.state.set(next);
|
|
34
|
+
if (next.attempt?.status === 'complete') {
|
|
35
|
+
if (next.ticket) {
|
|
36
|
+
await this.client.post('/v1/client/tickets/exchange', {
|
|
37
|
+
attempt_id: next.attempt.id,
|
|
38
|
+
ticket: next.ticket,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
await this.reload();
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// A magic-link step may now be pollable (a link opened on another device).
|
|
45
|
+
this.syncPolling();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** Start/stop the §5.3 magic-link poll to match the current state. */
|
|
49
|
+
syncPolling() {
|
|
50
|
+
if (shouldKeepPolling(this.state())) {
|
|
51
|
+
this.startPolling();
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.stopPolling();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
startPolling() {
|
|
58
|
+
if (this.pollTimer)
|
|
59
|
+
return;
|
|
60
|
+
this.pollTimer = setInterval(() => {
|
|
61
|
+
void (async () => {
|
|
62
|
+
const { state: next, ticket } = await pollAttempt(this.client, this.state());
|
|
63
|
+
this.state.set(next);
|
|
64
|
+
if (!ticket || !next.attempt)
|
|
65
|
+
return;
|
|
66
|
+
// The ticket is exchanged by a normal request, so no session token ever
|
|
67
|
+
// appears in a URL.
|
|
68
|
+
await this.client.post('/v1/client/tickets/exchange', {
|
|
69
|
+
attempt_id: next.attempt.id,
|
|
70
|
+
ticket,
|
|
71
|
+
});
|
|
72
|
+
await this.reload();
|
|
73
|
+
this.stopPolling();
|
|
74
|
+
})();
|
|
75
|
+
}, 2_000);
|
|
76
|
+
}
|
|
77
|
+
stopPolling() {
|
|
78
|
+
if (this.pollTimer) {
|
|
79
|
+
clearInterval(this.pollTimer);
|
|
80
|
+
this.pollTimer = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Release the poll timer — call from the component's `ngOnDestroy`. */
|
|
84
|
+
destroy() {
|
|
85
|
+
this.stopPolling();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxvdy1jb250cm9sbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL2Zsb3ctY29udHJvbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWtCLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2RCxPQUFPLEVBRUwsT0FBTyxFQUNQLGVBQWUsRUFDZixXQUFXLEVBQ1gsV0FBVyxFQUNYLGlCQUFpQixHQUVsQixNQUFNLGVBQWUsQ0FBQztBQUV2Qjs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFLWDtJQUNBO0lBTFYsS0FBSyxDQUE0QjtJQUNsQyxTQUFTLEdBQTBDLElBQUksQ0FBQztJQUVoRSxZQUNtQixNQUFrQixFQUNsQixNQUEyQixFQUM1QyxPQUE4QztRQUY3QixXQUFNLEdBQU4sTUFBTSxDQUFZO1FBQ2xCLFdBQU0sR0FBTixNQUFNLENBQXFCO1FBRzVDLDhFQUE4RTtRQUM5RSw2RUFBNkU7UUFDN0UsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQVksT0FBTyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ25GLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBOEI7UUFDekMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFekUsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDOUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFckIsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUN4QyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDaEIsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyw2QkFBNkIsRUFBRTtvQkFDcEQsVUFBVSxFQUFHLElBQUksQ0FBQyxPQUEyQixDQUFDLEVBQUU7b0JBQ2hELE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtpQkFDcEIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUNELE1BQU0sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ3RCLENBQUM7YUFBTSxDQUFDO1lBQ04sMkVBQTJFO1lBQzNFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVELHNFQUFzRTtJQUN0RSxXQUFXO1FBQ1QsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVPLFlBQVk7UUFDbEIsSUFBSSxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFDM0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1lBQ2hDLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDZixNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxNQUFNLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO2dCQUM3RSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDckIsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPO29CQUFFLE9BQU87Z0JBRXJDLHdFQUF3RTtnQkFDeEUsb0JBQW9CO2dCQUNwQixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLDZCQUE2QixFQUFFO29CQUNwRCxVQUFVLEVBQUcsSUFBSSxDQUFDLE9BQTJCLENBQUMsRUFBRTtvQkFDaEQsTUFBTTtpQkFDUCxDQUFDLENBQUM7Z0JBQ0gsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ1AsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ1osQ0FBQztJQUVPLFdBQVc7UUFDakIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbkIsYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN4QixDQUFDO0lBQ0gsQ0FBQztJQUVELHdFQUF3RTtJQUN4RSxPQUFPO1FBQ0wsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdyaXRhYmxlU2lnbmFsLCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEZhcGlDbGllbnQsXG4gIGFkdmFuY2UsXG4gIGZsb3dGcm9tUGVuZGluZyxcbiAgaW5pdGlhbEZsb3csXG4gIHBvbGxBdHRlbXB0LFxuICBzaG91bGRLZWVwUG9sbGluZyxcbiAgdHlwZSBGbG93U3RhdGUsXG59IGZyb20gJ0BhdGxhc2F1dGgvanMnO1xuXG4vKipcbiAqIFRoZSBzZXJ2ZXItZHJpdmVuIHNpZ24taW4gLyBzaWduLXVwIGVuZ2luZSwgc2hhcmVkIGJ5IGA8YXRsYXMtc2lnbi1pbj5gIGFuZFxuICogYDxhdGxhcy1zaWduLXVwPmAg4oCUIHRoZSBBbmd1bGFyIGNvdW50ZXJwYXJ0IG9mIFJlYWN0J3MgYHVzZUZsb3dgIGhvb2suXG4gKlxuICogSXQgb3ducyBubyBkZWNpc2lvbiBhYm91dCB3aGF0IGNvbWVzIG5leHQ6IGV2ZXJ5IHN0YXR1cyBjb21lcyBiYWNrIGZyb20gdGhlXG4gKiBzZXJ2ZXIgdmlhIGBhZHZhbmNlYCwgYW5kIHRoaXMgY29udHJvbGxlciBvbmx5IHBvc3RzIHdoYXRldmVyIHRoZSBjdXJyZW50IHN0ZXBcbiAqIG5lZWRzIGFuZCByZS1yZW5kZXJzIHRoZSByZXR1cm5lZCBzdGF0dXMuIFN0YXRlIGxpdmVzIGluIGEgc2lnbmFsIHNvIHRlbXBsYXRlc1xuICogdXBkYXRlIHdoZXRoZXIgdGhlIGFwcCBydW5zIHpvbmVkIG9yIHpvbmVsZXNzLlxuICovXG5leHBvcnQgY2xhc3MgQXRsYXNGbG93Q29udHJvbGxlciB7XG4gIHJlYWRvbmx5IHN0YXRlOiBXcml0YWJsZVNpZ25hbDxGbG93U3RhdGU+O1xuICBwcml2YXRlIHBvbGxUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBjbGllbnQ6IEZhcGlDbGllbnQsXG4gICAgcHJpdmF0ZSByZWFkb25seSByZWxvYWQ6ICgpID0+IFByb21pc2U8dm9pZD4sXG4gICAgcGVuZGluZzogeyBpZDogc3RyaW5nOyBzdGF0dXM6IHN0cmluZyB9IHwgbnVsbCxcbiAgKSB7XG4gICAgLy8gU2VlZGVkIGZyb20gYSByZWRpcmVjdCB0aGF0IGNhbWUgYmFjayBtaWQtZmxvdyAoZS5nLiBPQXV0aCBuZWVkaW5nIGEgc2Vjb25kXG4gICAgLy8gZmFjdG9yKSBzbyB0aGUgdXNlciByZXN1bWVzIGF0IHRoZSBkZW1hbmRlZCBzdGVwIGluc3RlYWQgb2Ygc3RhcnRpbmcgb3Zlci5cbiAgICB0aGlzLnN0YXRlID0gc2lnbmFsPEZsb3dTdGF0ZT4ocGVuZGluZyA/IGZsb3dGcm9tUGVuZGluZyhwZW5kaW5nKSA6IGluaXRpYWxGbG93KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZHZhbmNlIHRoZSBmbG93IHdpdGggdGhlIHZhbHVlcyB0aGUgdXNlciB0eXBlZC4gT24gY29tcGxldGlvbiwgZXhjaGFuZ2UgdGhlXG4gICAqIG9uZS10aW1lIHRpY2tldCBmb3IgY29va2llcyBvdmVyIGEgc2FtZS1vcmlnaW4gcmVxdWVzdCAoRkFQSSBpcyBjcm9zcy1vcmlnaW5cbiAgICogYW5kIGNhbm5vdCBzZXQgdGhlIGNvb2tpZSBvbiBpdHMgb3duIHJlc3BvbnNlKSwgdGhlbiByZS1ib290IHNvIHRoZSByZXN0IG9mXG4gICAqIHRoZSBhcHAgc2VlcyBhIHNpZ25lZC1pbiB1c2VyLlxuICAgKi9cbiAgYXN5bmMgc3VibWl0KHZhbHVlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc3RhdGUudXBkYXRlKChjdXJyZW50KSA9PiAoeyAuLi5jdXJyZW50LCBidXN5OiB0cnVlLCBlcnJvcnM6IFtdIH0pKTtcblxuICAgIGNvbnN0IG5leHQgPSBhd2FpdCBhZHZhbmNlKHRoaXMuY2xpZW50LCB0aGlzLnN0YXRlKCksIHZhbHVlcyk7XG4gICAgdGhpcy5zdGF0ZS5zZXQobmV4dCk7XG5cbiAgICBpZiAobmV4dC5hdHRlbXB0Py5zdGF0dXMgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgIGlmIChuZXh0LnRpY2tldCkge1xuICAgICAgICBhd2FpdCB0aGlzLmNsaWVudC5wb3N0KCcvdjEvY2xpZW50L3RpY2tldHMvZXhjaGFuZ2UnLCB7XG4gICAgICAgICAgYXR0ZW1wdF9pZDogKG5leHQuYXR0ZW1wdCBhcyB7IGlkPzogc3RyaW5nIH0pLmlkLFxuICAgICAgICAgIHRpY2tldDogbmV4dC50aWNrZXQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgYXdhaXQgdGhpcy5yZWxvYWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQSBtYWdpYy1saW5rIHN0ZXAgbWF5IG5vdyBiZSBwb2xsYWJsZSAoYSBsaW5rIG9wZW5lZCBvbiBhbm90aGVyIGRldmljZSkuXG4gICAgICB0aGlzLnN5bmNQb2xsaW5nKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFN0YXJ0L3N0b3AgdGhlIMKnNS4zIG1hZ2ljLWxpbmsgcG9sbCB0byBtYXRjaCB0aGUgY3VycmVudCBzdGF0ZS4gKi9cbiAgc3luY1BvbGxpbmcoKTogdm9pZCB7XG4gICAgaWYgKHNob3VsZEtlZXBQb2xsaW5nKHRoaXMuc3RhdGUoKSkpIHtcbiAgICAgIHRoaXMuc3RhcnRQb2xsaW5nKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3RvcFBvbGxpbmcoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0YXJ0UG9sbGluZygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wb2xsVGltZXIpIHJldHVybjtcbiAgICB0aGlzLnBvbGxUaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHZvaWQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgeyBzdGF0ZTogbmV4dCwgdGlja2V0IH0gPSBhd2FpdCBwb2xsQXR0ZW1wdCh0aGlzLmNsaWVudCwgdGhpcy5zdGF0ZSgpKTtcbiAgICAgICAgdGhpcy5zdGF0ZS5zZXQobmV4dCk7XG4gICAgICAgIGlmICghdGlja2V0IHx8ICFuZXh0LmF0dGVtcHQpIHJldHVybjtcblxuICAgICAgICAvLyBUaGUgdGlja2V0IGlzIGV4Y2hhbmdlZCBieSBhIG5vcm1hbCByZXF1ZXN0LCBzbyBubyBzZXNzaW9uIHRva2VuIGV2ZXJcbiAgICAgICAgLy8gYXBwZWFycyBpbiBhIFVSTC5cbiAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQucG9zdCgnL3YxL2NsaWVudC90aWNrZXRzL2V4Y2hhbmdlJywge1xuICAgICAgICAgIGF0dGVtcHRfaWQ6IChuZXh0LmF0dGVtcHQgYXMgeyBpZD86IHN0cmluZyB9KS5pZCxcbiAgICAgICAgICB0aWNrZXQsXG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZCgpO1xuICAgICAgICB0aGlzLnN0b3BQb2xsaW5nKCk7XG4gICAgICB9KSgpO1xuICAgIH0sIDJfMDAwKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RvcFBvbGxpbmcoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucG9sbFRpbWVyKSB7XG4gICAgICBjbGVhckludGVydmFsKHRoaXMucG9sbFRpbWVyKTtcbiAgICAgIHRoaXMucG9sbFRpbWVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKiogUmVsZWFzZSB0aGUgcG9sbCB0aW1lciDigJQgY2FsbCBmcm9tIHRoZSBjb21wb25lbnQncyBgbmdPbkRlc3Ryb3lgLiAqL1xuICBkZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3RvcFBvbGxpbmcoKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { AtlasProtectDirective } from '../directives/protect.directive';
|
|
4
|
+
import { classFor } from '../appearance';
|
|
5
|
+
import { translate } from '../i18n';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
/**
|
|
8
|
+
* `<atlas-organization-profile>` — the active organization's surface. The
|
|
9
|
+
* Angular peer of React's `<OrganizationProfile/>`. Management controls are
|
|
10
|
+
* gated on the ACTIVE org role via `*atlasProtect`, matching the server's rule
|
|
11
|
+
* rather than duplicating a looser one. Renders nothing with no active org.
|
|
12
|
+
*/
|
|
13
|
+
export class OrganizationProfileComponent {
|
|
14
|
+
atlas = inject(AtlasService);
|
|
15
|
+
t(key) {
|
|
16
|
+
return translate(this.atlas.localization, key);
|
|
17
|
+
}
|
|
18
|
+
cls(key, base) {
|
|
19
|
+
return classFor(key, this.atlas.appearance, base);
|
|
20
|
+
}
|
|
21
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OrganizationProfileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
22
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: OrganizationProfileComponent, isStandalone: true, selector: "atlas-organization-profile", ngImport: i0, template: `
|
|
23
|
+
@if (atlas.organization(); as membership) {
|
|
24
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
25
|
+
<h1>{{ membership.organization.name }}</h1>
|
|
26
|
+
<p>{{ t('organization.roleLabel') }}: {{ membership.role }}</p>
|
|
27
|
+
|
|
28
|
+
<button *atlasProtect="{ permission: 'org:sys_memberships:manage' }">
|
|
29
|
+
{{ t('organization.invite') }}
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
}
|
|
33
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: AtlasProtectDirective, selector: "[atlasProtect]", inputs: ["atlasProtect", "atlasProtectElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OrganizationProfileComponent, decorators: [{
|
|
36
|
+
type: Component,
|
|
37
|
+
args: [{
|
|
38
|
+
selector: 'atlas-organization-profile',
|
|
39
|
+
standalone: true,
|
|
40
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
41
|
+
imports: [AtlasProtectDirective],
|
|
42
|
+
template: `
|
|
43
|
+
@if (atlas.organization(); as membership) {
|
|
44
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
45
|
+
<h1>{{ membership.organization.name }}</h1>
|
|
46
|
+
<p>{{ t('organization.roleLabel') }}: {{ membership.role }}</p>
|
|
47
|
+
|
|
48
|
+
<button *atlasProtect="{ permission: 'org:sys_memberships:manage' }">
|
|
49
|
+
{{ t('organization.invite') }}
|
|
50
|
+
</button>
|
|
51
|
+
</div>
|
|
52
|
+
}
|
|
53
|
+
`,
|
|
54
|
+
}]
|
|
55
|
+
}] });
|
|
56
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pemF0aW9uLXByb2ZpbGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL29yZ2FuaXphdGlvbi1wcm9maWxlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDeEUsT0FBTyxFQUFFLFFBQVEsRUFBbUIsTUFBTSxlQUFlLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFFcEM7Ozs7O0dBS0c7QUFtQkgsTUFBTSxPQUFPLDRCQUE0QjtJQUNwQixLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXRDLENBQUMsQ0FBQyxHQUFXO1FBQ3JCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFUyxHQUFHLENBQUMsR0FBZSxFQUFFLElBQVk7UUFDekMsT0FBTyxRQUFRLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BELENBQUM7d0dBVFUsNEJBQTRCOzRGQUE1Qiw0QkFBNEIsc0ZBYjdCOzs7Ozs7Ozs7OztHQVdULDREQVpTLHFCQUFxQjs7NEZBY3BCLDRCQUE0QjtrQkFsQnhDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDRCQUE0QjtvQkFDdEMsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxPQUFPLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQztvQkFDaEMsUUFBUSxFQUFFOzs7Ozs7Ozs7OztHQVdUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdGxhc1NlcnZpY2UgfSBmcm9tICcuLi9hdGxhcy5zZXJ2aWNlJztcbmltcG9ydCB7IEF0bGFzUHJvdGVjdERpcmVjdGl2ZSB9IGZyb20gJy4uL2RpcmVjdGl2ZXMvcHJvdGVjdC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgY2xhc3NGb3IsIHR5cGUgRWxlbWVudEtleSB9IGZyb20gJy4uL2FwcGVhcmFuY2UnO1xuaW1wb3J0IHsgdHJhbnNsYXRlIH0gZnJvbSAnLi4vaTE4bic7XG5cbi8qKlxuICogYDxhdGxhcy1vcmdhbml6YXRpb24tcHJvZmlsZT5gIOKAlCB0aGUgYWN0aXZlIG9yZ2FuaXphdGlvbidzIHN1cmZhY2UuIFRoZVxuICogQW5ndWxhciBwZWVyIG9mIFJlYWN0J3MgYDxPcmdhbml6YXRpb25Qcm9maWxlLz5gLiBNYW5hZ2VtZW50IGNvbnRyb2xzIGFyZVxuICogZ2F0ZWQgb24gdGhlIEFDVElWRSBvcmcgcm9sZSB2aWEgYCphdGxhc1Byb3RlY3RgLCBtYXRjaGluZyB0aGUgc2VydmVyJ3MgcnVsZVxuICogcmF0aGVyIHRoYW4gZHVwbGljYXRpbmcgYSBsb29zZXIgb25lLiBSZW5kZXJzIG5vdGhpbmcgd2l0aCBubyBhY3RpdmUgb3JnLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhdGxhcy1vcmdhbml6YXRpb24tcHJvZmlsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbQXRsYXNQcm90ZWN0RGlyZWN0aXZlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKGF0bGFzLm9yZ2FuaXphdGlvbigpOyBhcyBtZW1iZXJzaGlwKSB7XG4gICAgICA8ZGl2IFtjbGFzc109XCJjbHMoJ2NhcmQnLCAnYXRsYXMtY2FyZCcpXCI+XG4gICAgICAgIDxoMT57eyBtZW1iZXJzaGlwLm9yZ2FuaXphdGlvbi5uYW1lIH19PC9oMT5cbiAgICAgICAgPHA+e3sgdCgnb3JnYW5pemF0aW9uLnJvbGVMYWJlbCcpIH19OiB7eyBtZW1iZXJzaGlwLnJvbGUgfX08L3A+XG5cbiAgICAgICAgPGJ1dHRvbiAqYXRsYXNQcm90ZWN0PVwieyBwZXJtaXNzaW9uOiAnb3JnOnN5c19tZW1iZXJzaGlwczptYW5hZ2UnIH1cIj5cbiAgICAgICAgICB7eyB0KCdvcmdhbml6YXRpb24uaW52aXRlJykgfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIE9yZ2FuaXphdGlvblByb2ZpbGVDb21wb25lbnQge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYXRsYXMgPSBpbmplY3QoQXRsYXNTZXJ2aWNlKTtcblxuICBwcm90ZWN0ZWQgdChrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRyYW5zbGF0ZSh0aGlzLmF0bGFzLmxvY2FsaXphdGlvbiwga2V5KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjbHMoa2V5OiBFbGVtZW50S2V5LCBiYXNlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBjbGFzc0ZvcihrZXksIHRoaXMuYXRsYXMuYXBwZWFyYW5jZSwgYmFzZSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { classFor } from '../appearance';
|
|
4
|
+
import { translate } from '../i18n';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* `<atlas-organization-switcher>` — switch the active organization (or the
|
|
8
|
+
* personal account). The Angular peer of React's `<OrganizationSwitcher/>`.
|
|
9
|
+
*/
|
|
10
|
+
export class OrganizationSwitcherComponent {
|
|
11
|
+
atlas = inject(AtlasService);
|
|
12
|
+
t(key) {
|
|
13
|
+
return translate(this.atlas.localization, key);
|
|
14
|
+
}
|
|
15
|
+
cls(key, base) {
|
|
16
|
+
return classFor(key, this.atlas.appearance, base);
|
|
17
|
+
}
|
|
18
|
+
setActive(organizationId) {
|
|
19
|
+
void this.atlas.setActiveOrganization(organizationId);
|
|
20
|
+
}
|
|
21
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OrganizationSwitcherComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
22
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: OrganizationSwitcherComponent, isStandalone: true, selector: "atlas-organization-switcher", ngImport: i0, template: `
|
|
23
|
+
<div [class]="cls('menu', 'atlas-menu')">
|
|
24
|
+
<button [class]="cls('menuItem', 'atlas-menu-item')" (click)="setActive(null)">
|
|
25
|
+
{{ t('organization.personal') }}
|
|
26
|
+
</button>
|
|
27
|
+
@for (membership of atlas.memberships(); track membership.organization.id) {
|
|
28
|
+
<button
|
|
29
|
+
[class]="cls('menuItem', 'atlas-menu-item')"
|
|
30
|
+
[disabled]="membership.organization.id === atlas.organization()?.organization?.id"
|
|
31
|
+
(click)="setActive(membership.organization.id)"
|
|
32
|
+
>
|
|
33
|
+
{{ membership.organization.name }}
|
|
34
|
+
</button>
|
|
35
|
+
}
|
|
36
|
+
</div>
|
|
37
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
38
|
+
}
|
|
39
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: OrganizationSwitcherComponent, decorators: [{
|
|
40
|
+
type: Component,
|
|
41
|
+
args: [{
|
|
42
|
+
selector: 'atlas-organization-switcher',
|
|
43
|
+
standalone: true,
|
|
44
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
45
|
+
template: `
|
|
46
|
+
<div [class]="cls('menu', 'atlas-menu')">
|
|
47
|
+
<button [class]="cls('menuItem', 'atlas-menu-item')" (click)="setActive(null)">
|
|
48
|
+
{{ t('organization.personal') }}
|
|
49
|
+
</button>
|
|
50
|
+
@for (membership of atlas.memberships(); track membership.organization.id) {
|
|
51
|
+
<button
|
|
52
|
+
[class]="cls('menuItem', 'atlas-menu-item')"
|
|
53
|
+
[disabled]="membership.organization.id === atlas.organization()?.organization?.id"
|
|
54
|
+
(click)="setActive(membership.organization.id)"
|
|
55
|
+
>
|
|
56
|
+
{{ membership.organization.name }}
|
|
57
|
+
</button>
|
|
58
|
+
}
|
|
59
|
+
</div>
|
|
60
|
+
`,
|
|
61
|
+
}]
|
|
62
|
+
}] });
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnYW5pemF0aW9uLXN3aXRjaGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbml6YXRpb24tc3dpdGNoZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFtQixNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFDOztBQUVwQzs7O0dBR0c7QUFzQkgsTUFBTSxPQUFPLDZCQUE2QjtJQUNyQixLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXRDLENBQUMsQ0FBQyxHQUFXO1FBQ3JCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFUyxHQUFHLENBQUMsR0FBZSxFQUFFLElBQVk7UUFDekMsT0FBTyxRQUFRLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFUyxTQUFTLENBQUMsY0FBNkI7UUFDL0MsS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7d0dBYlUsNkJBQTZCOzRGQUE3Qiw2QkFBNkIsdUZBakI5Qjs7Ozs7Ozs7Ozs7Ozs7O0dBZVQ7OzRGQUVVLDZCQUE2QjtrQkFyQnpDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDZCQUE2QjtvQkFDdkMsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7OztHQWVUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdGxhc1NlcnZpY2UgfSBmcm9tICcuLi9hdGxhcy5zZXJ2aWNlJztcbmltcG9ydCB7IGNsYXNzRm9yLCB0eXBlIEVsZW1lbnRLZXkgfSBmcm9tICcuLi9hcHBlYXJhbmNlJztcbmltcG9ydCB7IHRyYW5zbGF0ZSB9IGZyb20gJy4uL2kxOG4nO1xuXG4vKipcbiAqIGA8YXRsYXMtb3JnYW5pemF0aW9uLXN3aXRjaGVyPmAg4oCUIHN3aXRjaCB0aGUgYWN0aXZlIG9yZ2FuaXphdGlvbiAob3IgdGhlXG4gKiBwZXJzb25hbCBhY2NvdW50KS4gVGhlIEFuZ3VsYXIgcGVlciBvZiBSZWFjdCdzIGA8T3JnYW5pemF0aW9uU3dpdGNoZXIvPmAuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2F0bGFzLW9yZ2FuaXphdGlvbi1zd2l0Y2hlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNscygnbWVudScsICdhdGxhcy1tZW51JylcIj5cbiAgICAgIDxidXR0b24gW2NsYXNzXT1cImNscygnbWVudUl0ZW0nLCAnYXRsYXMtbWVudS1pdGVtJylcIiAoY2xpY2spPVwic2V0QWN0aXZlKG51bGwpXCI+XG4gICAgICAgIHt7IHQoJ29yZ2FuaXphdGlvbi5wZXJzb25hbCcpIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIEBmb3IgKG1lbWJlcnNoaXAgb2YgYXRsYXMubWVtYmVyc2hpcHMoKTsgdHJhY2sgbWVtYmVyc2hpcC5vcmdhbml6YXRpb24uaWQpIHtcbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIFtjbGFzc109XCJjbHMoJ21lbnVJdGVtJywgJ2F0bGFzLW1lbnUtaXRlbScpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwibWVtYmVyc2hpcC5vcmdhbml6YXRpb24uaWQgPT09IGF0bGFzLm9yZ2FuaXphdGlvbigpPy5vcmdhbml6YXRpb24/LmlkXCJcbiAgICAgICAgICAoY2xpY2spPVwic2V0QWN0aXZlKG1lbWJlcnNoaXAub3JnYW5pemF0aW9uLmlkKVwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBtZW1iZXJzaGlwLm9yZ2FuaXphdGlvbi5uYW1lIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBPcmdhbml6YXRpb25Td2l0Y2hlckNvbXBvbmVudCB7XG4gIHByb3RlY3RlZCByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuXG4gIHByb3RlY3RlZCB0KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdHJhbnNsYXRlKHRoaXMuYXRsYXMubG9jYWxpemF0aW9uLCBrZXkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNscyhrZXk6IEVsZW1lbnRLZXksIGJhc2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNsYXNzRm9yKGtleSwgdGhpcy5hdGxhcy5hcHBlYXJhbmNlLCBiYXNlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRBY3RpdmUob3JnYW5pemF0aW9uSWQ6IHN0cmluZyB8IG51bGwpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuYXRsYXMuc2V0QWN0aXZlT3JnYW5pemF0aW9uKG9yZ2FuaXphdGlvbklkKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input, inject, } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { AttemptFlowComponent } from './attempt-flow.component';
|
|
4
|
+
import { AtlasFlowController } from './flow-controller';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* `<atlas-sign-in>` — the full, multi-step sign-in flow driven entirely by the
|
|
8
|
+
* server-side attempt status. The Angular peer of React's `<SignIn/>`.
|
|
9
|
+
*
|
|
10
|
+
* ```html
|
|
11
|
+
* <atlas-sign-in *atlasSignedOut afterUrl="/dashboard"></atlas-sign-in>
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export class SignInComponent {
|
|
15
|
+
atlas = inject(AtlasService);
|
|
16
|
+
/** Where to send the user once the flow completes. Reserved for host routing. */
|
|
17
|
+
afterUrl;
|
|
18
|
+
flow = new AtlasFlowController(this.atlas.createFapiClient(), () => this.atlas.reload(),
|
|
19
|
+
// Resume mid-flow if an OAuth redirect came back owing a second factor.
|
|
20
|
+
this.atlas.pendingAttempt);
|
|
21
|
+
ngOnInit() {
|
|
22
|
+
// If seeded from a pending attempt that is already pollable, start polling.
|
|
23
|
+
this.flow.syncPolling();
|
|
24
|
+
}
|
|
25
|
+
ngOnDestroy() {
|
|
26
|
+
this.flow.destroy();
|
|
27
|
+
}
|
|
28
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SignInComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
29
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SignInComponent, isStandalone: true, selector: "atlas-sign-in", inputs: { afterUrl: "afterUrl" }, ngImport: i0, template: `
|
|
30
|
+
<atlas-attempt-flow
|
|
31
|
+
[attempt]="flow.state().attempt"
|
|
32
|
+
[busy]="flow.state().busy"
|
|
33
|
+
[errors]="flow.state().errors"
|
|
34
|
+
titleKey="signIn.title"
|
|
35
|
+
(submitFlow)="flow.submit($event)"
|
|
36
|
+
></atlas-attempt-flow>
|
|
37
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AttemptFlowComponent, selector: "atlas-attempt-flow", inputs: ["attempt", "busy", "errors", "titleKey"], outputs: ["submitFlow"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
38
|
+
}
|
|
39
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SignInComponent, decorators: [{
|
|
40
|
+
type: Component,
|
|
41
|
+
args: [{
|
|
42
|
+
selector: 'atlas-sign-in',
|
|
43
|
+
standalone: true,
|
|
44
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
45
|
+
imports: [AttemptFlowComponent],
|
|
46
|
+
template: `
|
|
47
|
+
<atlas-attempt-flow
|
|
48
|
+
[attempt]="flow.state().attempt"
|
|
49
|
+
[busy]="flow.state().busy"
|
|
50
|
+
[errors]="flow.state().errors"
|
|
51
|
+
titleKey="signIn.title"
|
|
52
|
+
(submitFlow)="flow.submit($event)"
|
|
53
|
+
></atlas-attempt-flow>
|
|
54
|
+
`,
|
|
55
|
+
}]
|
|
56
|
+
}], propDecorators: { afterUrl: [{
|
|
57
|
+
type: Input
|
|
58
|
+
}] } });
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi1pbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvc2lnbi1pbi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsS0FBSyxFQUdMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBRXhEOzs7Ozs7O0dBT0c7QUFnQkgsTUFBTSxPQUFPLGVBQWU7SUFDVCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRTlDLGlGQUFpRjtJQUN4RSxRQUFRLENBQVU7SUFFUixJQUFJLEdBQUcsSUFBSSxtQkFBbUIsQ0FDL0MsSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxFQUM3QixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRTtJQUN6Qix3RUFBd0U7SUFDeEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQzFCLENBQUM7SUFFRixRQUFRO1FBQ04sNEVBQTRFO1FBQzVFLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3RCLENBQUM7d0dBcEJVLGVBQWU7NEZBQWYsZUFBZSwyR0FWaEI7Ozs7Ozs7O0dBUVQsNERBVFMsb0JBQW9COzs0RkFXbkIsZUFBZTtrQkFmM0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsZUFBZTtvQkFDekIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxPQUFPLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQztvQkFDL0IsUUFBUSxFQUFFOzs7Ozs7OztHQVFUO2lCQUNGOzhCQUtVLFFBQVE7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIGluamVjdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdGxhc1NlcnZpY2UgfSBmcm9tICcuLi9hdGxhcy5zZXJ2aWNlJztcbmltcG9ydCB7IEF0dGVtcHRGbG93Q29tcG9uZW50IH0gZnJvbSAnLi9hdHRlbXB0LWZsb3cuY29tcG9uZW50JztcbmltcG9ydCB7IEF0bGFzRmxvd0NvbnRyb2xsZXIgfSBmcm9tICcuL2Zsb3ctY29udHJvbGxlcic7XG5cbi8qKlxuICogYDxhdGxhcy1zaWduLWluPmAg4oCUIHRoZSBmdWxsLCBtdWx0aS1zdGVwIHNpZ24taW4gZmxvdyBkcml2ZW4gZW50aXJlbHkgYnkgdGhlXG4gKiBzZXJ2ZXItc2lkZSBhdHRlbXB0IHN0YXR1cy4gVGhlIEFuZ3VsYXIgcGVlciBvZiBSZWFjdCdzIGA8U2lnbkluLz5gLlxuICpcbiAqIGBgYGh0bWxcbiAqIDxhdGxhcy1zaWduLWluICphdGxhc1NpZ25lZE91dCBhZnRlclVybD1cIi9kYXNoYm9hcmRcIj48L2F0bGFzLXNpZ24taW4+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXRsYXMtc2lnbi1pbicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBpbXBvcnRzOiBbQXR0ZW1wdEZsb3dDb21wb25lbnRdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxhdGxhcy1hdHRlbXB0LWZsb3dcbiAgICAgIFthdHRlbXB0XT1cImZsb3cuc3RhdGUoKS5hdHRlbXB0XCJcbiAgICAgIFtidXN5XT1cImZsb3cuc3RhdGUoKS5idXN5XCJcbiAgICAgIFtlcnJvcnNdPVwiZmxvdy5zdGF0ZSgpLmVycm9yc1wiXG4gICAgICB0aXRsZUtleT1cInNpZ25Jbi50aXRsZVwiXG4gICAgICAoc3VibWl0Rmxvdyk9XCJmbG93LnN1Ym1pdCgkZXZlbnQpXCJcbiAgICA+PC9hdGxhcy1hdHRlbXB0LWZsb3c+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25JbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuXG4gIC8qKiBXaGVyZSB0byBzZW5kIHRoZSB1c2VyIG9uY2UgdGhlIGZsb3cgY29tcGxldGVzLiBSZXNlcnZlZCBmb3IgaG9zdCByb3V0aW5nLiAqL1xuICBASW5wdXQoKSBhZnRlclVybD86IHN0cmluZztcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZmxvdyA9IG5ldyBBdGxhc0Zsb3dDb250cm9sbGVyKFxuICAgIHRoaXMuYXRsYXMuY3JlYXRlRmFwaUNsaWVudCgpLFxuICAgICgpID0+IHRoaXMuYXRsYXMucmVsb2FkKCksXG4gICAgLy8gUmVzdW1lIG1pZC1mbG93IGlmIGFuIE9BdXRoIHJlZGlyZWN0IGNhbWUgYmFjayBvd2luZyBhIHNlY29uZCBmYWN0b3IuXG4gICAgdGhpcy5hdGxhcy5wZW5kaW5nQXR0ZW1wdCxcbiAgKTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBJZiBzZWVkZWQgZnJvbSBhIHBlbmRpbmcgYXR0ZW1wdCB0aGF0IGlzIGFscmVhZHkgcG9sbGFibGUsIHN0YXJ0IHBvbGxpbmcuXG4gICAgdGhpcy5mbG93LnN5bmNQb2xsaW5nKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmZsb3cuZGVzdHJveSgpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input, inject, } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { AttemptFlowComponent } from './attempt-flow.component';
|
|
4
|
+
import { AtlasFlowController } from './flow-controller';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* `<atlas-sign-up>` — the full, server-driven sign-up flow. The Angular peer of
|
|
8
|
+
* React's `<SignUp/>`. It shares the exact flow engine with `<atlas-sign-in>`;
|
|
9
|
+
* only the title differs, because the sequence of steps is decided by the server.
|
|
10
|
+
*
|
|
11
|
+
* ```html
|
|
12
|
+
* <atlas-sign-up *atlasSignedOut></atlas-sign-up>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export class SignUpComponent {
|
|
16
|
+
atlas = inject(AtlasService);
|
|
17
|
+
/** Where to send the user once the flow completes. Reserved for host routing. */
|
|
18
|
+
afterUrl;
|
|
19
|
+
flow = new AtlasFlowController(this.atlas.createFapiClient(), () => this.atlas.reload(), this.atlas.pendingAttempt);
|
|
20
|
+
ngOnDestroy() {
|
|
21
|
+
this.flow.destroy();
|
|
22
|
+
}
|
|
23
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SignUpComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
24
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SignUpComponent, isStandalone: true, selector: "atlas-sign-up", inputs: { afterUrl: "afterUrl" }, ngImport: i0, template: `
|
|
25
|
+
<atlas-attempt-flow
|
|
26
|
+
[attempt]="flow.state().attempt"
|
|
27
|
+
[busy]="flow.state().busy"
|
|
28
|
+
[errors]="flow.state().errors"
|
|
29
|
+
titleKey="signUp.title"
|
|
30
|
+
(submitFlow)="flow.submit($event)"
|
|
31
|
+
></atlas-attempt-flow>
|
|
32
|
+
`, isInline: true, dependencies: [{ kind: "component", type: AttemptFlowComponent, selector: "atlas-attempt-flow", inputs: ["attempt", "busy", "errors", "titleKey"], outputs: ["submitFlow"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
33
|
+
}
|
|
34
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SignUpComponent, decorators: [{
|
|
35
|
+
type: Component,
|
|
36
|
+
args: [{
|
|
37
|
+
selector: 'atlas-sign-up',
|
|
38
|
+
standalone: true,
|
|
39
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
40
|
+
imports: [AttemptFlowComponent],
|
|
41
|
+
template: `
|
|
42
|
+
<atlas-attempt-flow
|
|
43
|
+
[attempt]="flow.state().attempt"
|
|
44
|
+
[busy]="flow.state().busy"
|
|
45
|
+
[errors]="flow.state().errors"
|
|
46
|
+
titleKey="signUp.title"
|
|
47
|
+
(submitFlow)="flow.submit($event)"
|
|
48
|
+
></atlas-attempt-flow>
|
|
49
|
+
`,
|
|
50
|
+
}]
|
|
51
|
+
}], propDecorators: { afterUrl: [{
|
|
52
|
+
type: Input
|
|
53
|
+
}] } });
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi11cC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvc2lnbi11cC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsS0FBSyxFQUVMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBRXhEOzs7Ozs7OztHQVFHO0FBZ0JILE1BQU0sT0FBTyxlQUFlO0lBQ1QsS0FBSyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU5QyxpRkFBaUY7SUFDeEUsUUFBUSxDQUFVO0lBRVIsSUFBSSxHQUFHLElBQUksbUJBQW1CLENBQy9DLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsRUFDN0IsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQzFCLENBQUM7SUFFRixXQUFXO1FBQ1QsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUN0QixDQUFDO3dHQWRVLGVBQWU7NEZBQWYsZUFBZSwyR0FWaEI7Ozs7Ozs7O0dBUVQsNERBVFMsb0JBQW9COzs0RkFXbkIsZUFBZTtrQkFmM0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsZUFBZTtvQkFDekIsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxPQUFPLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQztvQkFDL0IsUUFBUSxFQUFFOzs7Ozs7OztHQVFUO2lCQUNGOzhCQUtVLFFBQVE7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXRsYXNTZXJ2aWNlIH0gZnJvbSAnLi4vYXRsYXMuc2VydmljZSc7XG5pbXBvcnQgeyBBdHRlbXB0Rmxvd0NvbXBvbmVudCB9IGZyb20gJy4vYXR0ZW1wdC1mbG93LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBBdGxhc0Zsb3dDb250cm9sbGVyIH0gZnJvbSAnLi9mbG93LWNvbnRyb2xsZXInO1xuXG4vKipcbiAqIGA8YXRsYXMtc2lnbi11cD5gIOKAlCB0aGUgZnVsbCwgc2VydmVyLWRyaXZlbiBzaWduLXVwIGZsb3cuIFRoZSBBbmd1bGFyIHBlZXIgb2ZcbiAqIFJlYWN0J3MgYDxTaWduVXAvPmAuIEl0IHNoYXJlcyB0aGUgZXhhY3QgZmxvdyBlbmdpbmUgd2l0aCBgPGF0bGFzLXNpZ24taW4+YDtcbiAqIG9ubHkgdGhlIHRpdGxlIGRpZmZlcnMsIGJlY2F1c2UgdGhlIHNlcXVlbmNlIG9mIHN0ZXBzIGlzIGRlY2lkZWQgYnkgdGhlIHNlcnZlci5cbiAqXG4gKiBgYGBodG1sXG4gKiA8YXRsYXMtc2lnbi11cCAqYXRsYXNTaWduZWRPdXQ+PC9hdGxhcy1zaWduLXVwPlxuICogYGBgXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2F0bGFzLXNpZ24tdXAnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW0F0dGVtcHRGbG93Q29tcG9uZW50XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8YXRsYXMtYXR0ZW1wdC1mbG93XG4gICAgICBbYXR0ZW1wdF09XCJmbG93LnN0YXRlKCkuYXR0ZW1wdFwiXG4gICAgICBbYnVzeV09XCJmbG93LnN0YXRlKCkuYnVzeVwiXG4gICAgICBbZXJyb3JzXT1cImZsb3cuc3RhdGUoKS5lcnJvcnNcIlxuICAgICAgdGl0bGVLZXk9XCJzaWduVXAudGl0bGVcIlxuICAgICAgKHN1Ym1pdEZsb3cpPVwiZmxvdy5zdWJtaXQoJGV2ZW50KVwiXG4gICAgPjwvYXRsYXMtYXR0ZW1wdC1mbG93PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBTaWduVXBDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHJlYWRvbmx5IGF0bGFzID0gaW5qZWN0KEF0bGFzU2VydmljZSk7XG5cbiAgLyoqIFdoZXJlIHRvIHNlbmQgdGhlIHVzZXIgb25jZSB0aGUgZmxvdyBjb21wbGV0ZXMuIFJlc2VydmVkIGZvciBob3N0IHJvdXRpbmcuICovXG4gIEBJbnB1dCgpIGFmdGVyVXJsPzogc3RyaW5nO1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBmbG93ID0gbmV3IEF0bGFzRmxvd0NvbnRyb2xsZXIoXG4gICAgdGhpcy5hdGxhcy5jcmVhdGVGYXBpQ2xpZW50KCksXG4gICAgKCkgPT4gdGhpcy5hdGxhcy5yZWxvYWQoKSxcbiAgICB0aGlzLmF0bGFzLnBlbmRpbmdBdHRlbXB0LFxuICApO1xuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZmxvdy5kZXN0cm95KCk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { classFor } from '../appearance';
|
|
4
|
+
import { translate } from '../i18n';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* `<atlas-user-button>` — the signed-in user's avatar with a drop-down that can
|
|
8
|
+
* sign them out. The Angular peer of React's `<UserButton/>`. Renders nothing
|
|
9
|
+
* when there is no user.
|
|
10
|
+
*/
|
|
11
|
+
export class UserButtonComponent {
|
|
12
|
+
atlas = inject(AtlasService);
|
|
13
|
+
open = signal(false);
|
|
14
|
+
label = computed(() => {
|
|
15
|
+
const user = this.atlas.user();
|
|
16
|
+
if (!user)
|
|
17
|
+
return '';
|
|
18
|
+
return [user.first_name, user.last_name].filter(Boolean).join(' ') || user.username || '';
|
|
19
|
+
});
|
|
20
|
+
t(key) {
|
|
21
|
+
return translate(this.atlas.localization, key);
|
|
22
|
+
}
|
|
23
|
+
cls(key, base) {
|
|
24
|
+
return classFor(key, this.atlas.appearance, base);
|
|
25
|
+
}
|
|
26
|
+
toggle() {
|
|
27
|
+
this.open.update((o) => !o);
|
|
28
|
+
}
|
|
29
|
+
signOut() {
|
|
30
|
+
void this.atlas.signOut();
|
|
31
|
+
}
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
33
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: UserButtonComponent, isStandalone: true, selector: "atlas-user-button", ngImport: i0, template: `
|
|
34
|
+
@if (atlas.user(); as user) {
|
|
35
|
+
<div class="atlas-user-button">
|
|
36
|
+
<button
|
|
37
|
+
[class]="cls('avatar', 'atlas-avatar')"
|
|
38
|
+
[attr.aria-expanded]="open()"
|
|
39
|
+
(click)="toggle()"
|
|
40
|
+
>
|
|
41
|
+
@if (user.image_url) {
|
|
42
|
+
<img [src]="user.image_url" alt="" />
|
|
43
|
+
} @else {
|
|
44
|
+
<span>{{ label().slice(0, 1) }}</span>
|
|
45
|
+
}
|
|
46
|
+
</button>
|
|
47
|
+
|
|
48
|
+
@if (open()) {
|
|
49
|
+
<div [class]="cls('menu', 'atlas-menu')" role="menu">
|
|
50
|
+
<span [class]="cls('menuItem', 'atlas-menu-item')">{{ label() }}</span>
|
|
51
|
+
<button [class]="cls('menuItem', 'atlas-menu-item')" (click)="signOut()">
|
|
52
|
+
{{ t('userButton.signOut') }}
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
}
|
|
56
|
+
</div>
|
|
57
|
+
}
|
|
58
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserButtonComponent, decorators: [{
|
|
61
|
+
type: Component,
|
|
62
|
+
args: [{
|
|
63
|
+
selector: 'atlas-user-button',
|
|
64
|
+
standalone: true,
|
|
65
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
66
|
+
template: `
|
|
67
|
+
@if (atlas.user(); as user) {
|
|
68
|
+
<div class="atlas-user-button">
|
|
69
|
+
<button
|
|
70
|
+
[class]="cls('avatar', 'atlas-avatar')"
|
|
71
|
+
[attr.aria-expanded]="open()"
|
|
72
|
+
(click)="toggle()"
|
|
73
|
+
>
|
|
74
|
+
@if (user.image_url) {
|
|
75
|
+
<img [src]="user.image_url" alt="" />
|
|
76
|
+
} @else {
|
|
77
|
+
<span>{{ label().slice(0, 1) }}</span>
|
|
78
|
+
}
|
|
79
|
+
</button>
|
|
80
|
+
|
|
81
|
+
@if (open()) {
|
|
82
|
+
<div [class]="cls('menu', 'atlas-menu')" role="menu">
|
|
83
|
+
<span [class]="cls('menuItem', 'atlas-menu-item')">{{ label() }}</span>
|
|
84
|
+
<button [class]="cls('menuItem', 'atlas-menu-item')" (click)="signOut()">
|
|
85
|
+
{{ t('userButton.signOut') }}
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
}
|
|
89
|
+
</div>
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
92
|
+
}]
|
|
93
|
+
}] });
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1idXR0b24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3VzZXItYnV0dG9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFtQixNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFDOztBQUVwQzs7OztHQUlHO0FBZ0NILE1BQU0sT0FBTyxtQkFBbUI7SUFDWCxLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzdCLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFckIsS0FBSyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7UUFDdkMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3JCLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO0lBQzVGLENBQUMsQ0FBQyxDQUFDO0lBRU8sQ0FBQyxDQUFDLEdBQVc7UUFDckIsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVTLEdBQUcsQ0FBQyxHQUFlLEVBQUUsSUFBWTtRQUN6QyxPQUFPLFFBQVEsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVTLE1BQU07UUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRVMsT0FBTztRQUNmLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUM1QixDQUFDO3dHQXhCVSxtQkFBbUI7NEZBQW5CLG1CQUFtQiw2RUEzQnBCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUJUOzs0RkFFVSxtQkFBbUI7a0JBL0IvQixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxtQkFBbUI7b0JBQzdCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUJUO2lCQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgY29tcHV0ZWQsIGluamVjdCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdGxhc1NlcnZpY2UgfSBmcm9tICcuLi9hdGxhcy5zZXJ2aWNlJztcbmltcG9ydCB7IGNsYXNzRm9yLCB0eXBlIEVsZW1lbnRLZXkgfSBmcm9tICcuLi9hcHBlYXJhbmNlJztcbmltcG9ydCB7IHRyYW5zbGF0ZSB9IGZyb20gJy4uL2kxOG4nO1xuXG4vKipcbiAqIGA8YXRsYXMtdXNlci1idXR0b24+YCDigJQgdGhlIHNpZ25lZC1pbiB1c2VyJ3MgYXZhdGFyIHdpdGggYSBkcm9wLWRvd24gdGhhdCBjYW5cbiAqIHNpZ24gdGhlbSBvdXQuIFRoZSBBbmd1bGFyIHBlZXIgb2YgUmVhY3QncyBgPFVzZXJCdXR0b24vPmAuIFJlbmRlcnMgbm90aGluZ1xuICogd2hlbiB0aGVyZSBpcyBubyB1c2VyLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhdGxhcy11c2VyLWJ1dHRvbicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoYXRsYXMudXNlcigpOyBhcyB1c2VyKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwiYXRsYXMtdXNlci1idXR0b25cIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIFtjbGFzc109XCJjbHMoJ2F2YXRhcicsICdhdGxhcy1hdmF0YXInKVwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJvcGVuKClcIlxuICAgICAgICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICBAaWYgKHVzZXIuaW1hZ2VfdXJsKSB7XG4gICAgICAgICAgICA8aW1nIFtzcmNdPVwidXNlci5pbWFnZV91cmxcIiBhbHQ9XCJcIiAvPlxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPHNwYW4+e3sgbGFiZWwoKS5zbGljZSgwLCAxKSB9fTwvc3Bhbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgIEBpZiAob3BlbigpKSB7XG4gICAgICAgICAgPGRpdiBbY2xhc3NdPVwiY2xzKCdtZW51JywgJ2F0bGFzLW1lbnUnKVwiIHJvbGU9XCJtZW51XCI+XG4gICAgICAgICAgICA8c3BhbiBbY2xhc3NdPVwiY2xzKCdtZW51SXRlbScsICdhdGxhcy1tZW51LWl0ZW0nKVwiPnt7IGxhYmVsKCkgfX08L3NwYW4+XG4gICAgICAgICAgICA8YnV0dG9uIFtjbGFzc109XCJjbHMoJ21lbnVJdGVtJywgJ2F0bGFzLW1lbnUtaXRlbScpXCIgKGNsaWNrKT1cInNpZ25PdXQoKVwiPlxuICAgICAgICAgICAgICB7eyB0KCd1c2VyQnV0dG9uLnNpZ25PdXQnKSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgVXNlckJ1dHRvbkNvbXBvbmVudCB7XG4gIHByb3RlY3RlZCByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgb3BlbiA9IHNpZ25hbChmYWxzZSk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxhYmVsID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLmF0bGFzLnVzZXIoKTtcbiAgICBpZiAoIXVzZXIpIHJldHVybiAnJztcbiAgICByZXR1cm4gW3VzZXIuZmlyc3RfbmFtZSwgdXNlci5sYXN0X25hbWVdLmZpbHRlcihCb29sZWFuKS5qb2luKCcgJykgfHwgdXNlci51c2VybmFtZSB8fCAnJztcbiAgfSk7XG5cbiAgcHJvdGVjdGVkIHQoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0cmFuc2xhdGUodGhpcy5hdGxhcy5sb2NhbGl6YXRpb24sIGtleSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY2xzKGtleTogRWxlbWVudEtleSwgYmFzZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY2xhc3NGb3Ioa2V5LCB0aGlzLmF0bGFzLmFwcGVhcmFuY2UsIGJhc2UpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHRvZ2dsZSgpOiB2b2lkIHtcbiAgICB0aGlzLm9wZW4udXBkYXRlKChvKSA9PiAhbyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2lnbk91dCgpOiB2b2lkIHtcbiAgICB2b2lkIHRoaXMuYXRsYXMuc2lnbk91dCgpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import { classFor } from '../appearance';
|
|
4
|
+
import { translate } from '../i18n';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* `<atlas-user-profile>` — the signed-in user's account surface (emails,
|
|
8
|
+
* security). The Angular peer of React's `<UserProfile/>`. Renders nothing when
|
|
9
|
+
* there is no user.
|
|
10
|
+
*/
|
|
11
|
+
export class UserProfileComponent {
|
|
12
|
+
atlas = inject(AtlasService);
|
|
13
|
+
t(key) {
|
|
14
|
+
return translate(this.atlas.localization, key);
|
|
15
|
+
}
|
|
16
|
+
cls(key, base) {
|
|
17
|
+
return classFor(key, this.atlas.appearance, base);
|
|
18
|
+
}
|
|
19
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserProfileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: UserProfileComponent, isStandalone: true, selector: "atlas-user-profile", ngImport: i0, template: `
|
|
21
|
+
@if (atlas.user(); as user) {
|
|
22
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
23
|
+
<h1>{{ t('userProfile.title') }}</h1>
|
|
24
|
+
|
|
25
|
+
<section>
|
|
26
|
+
<h2>{{ t('userProfile.emailsSection') }}</h2>
|
|
27
|
+
<ul>
|
|
28
|
+
@for (email of user.email_addresses ?? []; track email.id) {
|
|
29
|
+
<li>
|
|
30
|
+
{{ email.email_address }}
|
|
31
|
+
@if (!email.verified) {
|
|
32
|
+
<em> — {{ t('userProfile.unverified') }}</em>
|
|
33
|
+
}
|
|
34
|
+
</li>
|
|
35
|
+
}
|
|
36
|
+
</ul>
|
|
37
|
+
</section>
|
|
38
|
+
|
|
39
|
+
<section>
|
|
40
|
+
<h2>{{ t('userProfile.securitySection') }}</h2>
|
|
41
|
+
<p>{{ user.mfa_enabled ? '2FA on' : '2FA off' }}</p>
|
|
42
|
+
</section>
|
|
43
|
+
</div>
|
|
44
|
+
}
|
|
45
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
46
|
+
}
|
|
47
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserProfileComponent, decorators: [{
|
|
48
|
+
type: Component,
|
|
49
|
+
args: [{
|
|
50
|
+
selector: 'atlas-user-profile',
|
|
51
|
+
standalone: true,
|
|
52
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
53
|
+
template: `
|
|
54
|
+
@if (atlas.user(); as user) {
|
|
55
|
+
<div [class]="cls('card', 'atlas-card')">
|
|
56
|
+
<h1>{{ t('userProfile.title') }}</h1>
|
|
57
|
+
|
|
58
|
+
<section>
|
|
59
|
+
<h2>{{ t('userProfile.emailsSection') }}</h2>
|
|
60
|
+
<ul>
|
|
61
|
+
@for (email of user.email_addresses ?? []; track email.id) {
|
|
62
|
+
<li>
|
|
63
|
+
{{ email.email_address }}
|
|
64
|
+
@if (!email.verified) {
|
|
65
|
+
<em> — {{ t('userProfile.unverified') }}</em>
|
|
66
|
+
}
|
|
67
|
+
</li>
|
|
68
|
+
}
|
|
69
|
+
</ul>
|
|
70
|
+
</section>
|
|
71
|
+
|
|
72
|
+
<section>
|
|
73
|
+
<h2>{{ t('userProfile.securitySection') }}</h2>
|
|
74
|
+
<p>{{ user.mfa_enabled ? '2FA on' : '2FA off' }}</p>
|
|
75
|
+
</section>
|
|
76
|
+
</div>
|
|
77
|
+
}
|
|
78
|
+
`,
|
|
79
|
+
}]
|
|
80
|
+
}] });
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci1wcm9maWxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy91c2VyLXByb2ZpbGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsUUFBUSxFQUFtQixNQUFNLGVBQWUsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sU0FBUyxDQUFDOztBQUVwQzs7OztHQUlHO0FBZ0NILE1BQU0sT0FBTyxvQkFBb0I7SUFDWixLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXRDLENBQUMsQ0FBQyxHQUFXO1FBQ3JCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFUyxHQUFHLENBQUMsR0FBZSxFQUFFLElBQVk7UUFDekMsT0FBTyxRQUFRLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BELENBQUM7d0dBVFUsb0JBQW9COzRGQUFwQixvQkFBb0IsOEVBM0JyQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCVDs7NEZBRVUsb0JBQW9CO2tCQS9CaEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsb0JBQW9CO29CQUM5QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07b0JBQy9DLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCVDtpQkFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQXRsYXNTZXJ2aWNlIH0gZnJvbSAnLi4vYXRsYXMuc2VydmljZSc7XG5pbXBvcnQgeyBjbGFzc0ZvciwgdHlwZSBFbGVtZW50S2V5IH0gZnJvbSAnLi4vYXBwZWFyYW5jZSc7XG5pbXBvcnQgeyB0cmFuc2xhdGUgfSBmcm9tICcuLi9pMThuJztcblxuLyoqXG4gKiBgPGF0bGFzLXVzZXItcHJvZmlsZT5gIOKAlCB0aGUgc2lnbmVkLWluIHVzZXIncyBhY2NvdW50IHN1cmZhY2UgKGVtYWlscyxcbiAqIHNlY3VyaXR5KS4gVGhlIEFuZ3VsYXIgcGVlciBvZiBSZWFjdCdzIGA8VXNlclByb2ZpbGUvPmAuIFJlbmRlcnMgbm90aGluZyB3aGVuXG4gKiB0aGVyZSBpcyBubyB1c2VyLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhdGxhcy11c2VyLXByb2ZpbGUnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICBAaWYgKGF0bGFzLnVzZXIoKTsgYXMgdXNlcikge1xuICAgICAgPGRpdiBbY2xhc3NdPVwiY2xzKCdjYXJkJywgJ2F0bGFzLWNhcmQnKVwiPlxuICAgICAgICA8aDE+e3sgdCgndXNlclByb2ZpbGUudGl0bGUnKSB9fTwvaDE+XG5cbiAgICAgICAgPHNlY3Rpb24+XG4gICAgICAgICAgPGgyPnt7IHQoJ3VzZXJQcm9maWxlLmVtYWlsc1NlY3Rpb24nKSB9fTwvaDI+XG4gICAgICAgICAgPHVsPlxuICAgICAgICAgICAgQGZvciAoZW1haWwgb2YgdXNlci5lbWFpbF9hZGRyZXNzZXMgPz8gW107IHRyYWNrIGVtYWlsLmlkKSB7XG4gICAgICAgICAgICAgIDxsaT5cbiAgICAgICAgICAgICAgICB7eyBlbWFpbC5lbWFpbF9hZGRyZXNzIH19XG4gICAgICAgICAgICAgICAgQGlmICghZW1haWwudmVyaWZpZWQpIHtcbiAgICAgICAgICAgICAgICAgIDxlbT4g4oCUIHt7IHQoJ3VzZXJQcm9maWxlLnVudmVyaWZpZWQnKSB9fTwvZW0+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvdWw+XG4gICAgICAgIDwvc2VjdGlvbj5cblxuICAgICAgICA8c2VjdGlvbj5cbiAgICAgICAgICA8aDI+e3sgdCgndXNlclByb2ZpbGUuc2VjdXJpdHlTZWN0aW9uJykgfX08L2gyPlxuICAgICAgICAgIDxwPnt7IHVzZXIubWZhX2VuYWJsZWQgPyAnMkZBIG9uJyA6ICcyRkEgb2ZmJyB9fTwvcD5cbiAgICAgICAgPC9zZWN0aW9uPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBVc2VyUHJvZmlsZUNvbXBvbmVudCB7XG4gIHByb3RlY3RlZCByZWFkb25seSBhdGxhcyA9IGluamVjdChBdGxhc1NlcnZpY2UpO1xuXG4gIHByb3RlY3RlZCB0KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdHJhbnNsYXRlKHRoaXMuYXRsYXMubG9jYWxpemF0aW9uLCBrZXkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNscyhrZXk6IEVsZW1lbnRLZXksIGJhc2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNsYXNzRm9yKGtleSwgdGhpcy5hdGxhcy5hcHBlYXJhbmNlLCBiYXNlKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Directive, ElementRef, Renderer2, RendererStyleFlags2, inject, } from '@angular/core';
|
|
2
|
+
import { AtlasService } from '../atlas.service';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* `atlasRoot` — apply the resolved appearance design tokens as `--atlas-*` CSS
|
|
6
|
+
* custom properties (and the `atlas-root` class) onto its host element, so the
|
|
7
|
+
* Atlas components rendered inside inherit them.
|
|
8
|
+
*
|
|
9
|
+
* React does this with the wrapping `<div className="atlas-root" style={…}>`
|
|
10
|
+
* inside `<AtlasProvider>`. Angular has no single wrapping element, so a
|
|
11
|
+
* consumer opts in by putting `atlasRoot` on whatever element encloses the
|
|
12
|
+
* Atlas UI (commonly the app root):
|
|
13
|
+
*
|
|
14
|
+
* ```html
|
|
15
|
+
* <div atlasRoot>
|
|
16
|
+
* <router-outlet></router-outlet>
|
|
17
|
+
* </div>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class AtlasRootDirective {
|
|
21
|
+
atlas = inject(AtlasService);
|
|
22
|
+
el = inject(ElementRef);
|
|
23
|
+
renderer = inject(Renderer2);
|
|
24
|
+
ngOnInit() {
|
|
25
|
+
this.renderer.addClass(this.el.nativeElement, 'atlas-root');
|
|
26
|
+
const vars = this.atlas.appearanceVariables();
|
|
27
|
+
for (const [name, value] of Object.entries(vars)) {
|
|
28
|
+
// DashCase so a `--atlas-*` custom property is written verbatim, not camelCased.
|
|
29
|
+
this.renderer.setStyle(this.el.nativeElement, name, value, RendererStyleFlags2.DashCase);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
33
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: AtlasRootDirective, isStandalone: true, selector: "[atlasRoot]", ngImport: i0 });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasRootDirective, decorators: [{
|
|
36
|
+
type: Directive,
|
|
37
|
+
args: [{
|
|
38
|
+
selector: '[atlasRoot]',
|
|
39
|
+
standalone: true,
|
|
40
|
+
}]
|
|
41
|
+
}] });
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXRsYXMtcm9vdC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RpcmVjdGl2ZXMvYXRsYXMtcm9vdC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxVQUFVLEVBRVYsU0FBUyxFQUNULG1CQUFtQixFQUNuQixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDOztBQUVoRDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFLSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ1osS0FBSyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUM3QixFQUFFLEdBQUcsTUFBTSxDQUEwQixVQUFVLENBQUMsQ0FBQztJQUNqRCxRQUFRLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTlDLFFBQVE7UUFDTixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM1RCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDOUMsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNqRCxpRkFBaUY7WUFDakYsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzRixDQUFDO0lBQ0gsQ0FBQzt3R0FaVSxrQkFBa0I7NEZBQWxCLGtCQUFrQjs7NEZBQWxCLGtCQUFrQjtrQkFKOUIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsYUFBYTtvQkFDdkIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBPbkluaXQsXG4gIFJlbmRlcmVyMixcbiAgUmVuZGVyZXJTdHlsZUZsYWdzMixcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEF0bGFzU2VydmljZSB9IGZyb20gJy4uL2F0bGFzLnNlcnZpY2UnO1xuXG4vKipcbiAqIGBhdGxhc1Jvb3RgIOKAlCBhcHBseSB0aGUgcmVzb2x2ZWQgYXBwZWFyYW5jZSBkZXNpZ24gdG9rZW5zIGFzIGAtLWF0bGFzLSpgIENTU1xuICogY3VzdG9tIHByb3BlcnRpZXMgKGFuZCB0aGUgYGF0bGFzLXJvb3RgIGNsYXNzKSBvbnRvIGl0cyBob3N0IGVsZW1lbnQsIHNvIHRoZVxuICogQXRsYXMgY29tcG9uZW50cyByZW5kZXJlZCBpbnNpZGUgaW5oZXJpdCB0aGVtLlxuICpcbiAqIFJlYWN0IGRvZXMgdGhpcyB3aXRoIHRoZSB3cmFwcGluZyBgPGRpdiBjbGFzc05hbWU9XCJhdGxhcy1yb290XCIgc3R5bGU9e+KApn0+YFxuICogaW5zaWRlIGA8QXRsYXNQcm92aWRlcj5gLiBBbmd1bGFyIGhhcyBubyBzaW5nbGUgd3JhcHBpbmcgZWxlbWVudCwgc28gYVxuICogY29uc3VtZXIgb3B0cyBpbiBieSBwdXR0aW5nIGBhdGxhc1Jvb3RgIG9uIHdoYXRldmVyIGVsZW1lbnQgZW5jbG9zZXMgdGhlXG4gKiBBdGxhcyBVSSAoY29tbW9ubHkgdGhlIGFwcCByb290KTpcbiAqXG4gKiBgYGBodG1sXG4gKiA8ZGl2IGF0bGFzUm9vdD5cbiAqICAgPHJvdXRlci1vdXRsZXQ+PC9yb3V0ZXItb3V0bGV0PlxuICogPC9kaXY+XG4gKiBgYGBcbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2F0bGFzUm9vdF0nLFxuICBzdGFuZGFsb25lOiB0cnVlLFxufSlcbmV4cG9ydCBjbGFzcyBBdGxhc1Jvb3REaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQge1xuICBwcml2YXRlIHJlYWRvbmx5IGF0bGFzID0gaW5qZWN0KEF0bGFzU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZWwgPSBpbmplY3Q8RWxlbWVudFJlZjxIVE1MRWxlbWVudD4+KEVsZW1lbnRSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlbmRlcmVyID0gaW5qZWN0KFJlbmRlcmVyMik7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyh0aGlzLmVsLm5hdGl2ZUVsZW1lbnQsICdhdGxhcy1yb290Jyk7XG4gICAgY29uc3QgdmFycyA9IHRoaXMuYXRsYXMuYXBwZWFyYW5jZVZhcmlhYmxlcygpO1xuICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh2YXJzKSkge1xuICAgICAgLy8gRGFzaENhc2Ugc28gYSBgLS1hdGxhcy0qYCBjdXN0b20gcHJvcGVydHkgaXMgd3JpdHRlbiB2ZXJiYXRpbSwgbm90IGNhbWVsQ2FzZWQuXG4gICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZWwubmF0aXZlRWxlbWVudCwgbmFtZSwgdmFsdWUsIFJlbmRlcmVyU3R5bGVGbGFnczIuRGFzaENhc2UpO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Directive } from '@angular/core';
|
|
2
|
+
import { AtlasToggleDirective } from './toggle.directive';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* `*atlasLoaded` — render the template only once the SDK has finished booting.
|
|
6
|
+
* The Angular peer of React's `<AtlasLoaded>`, the symmetric partner of
|
|
7
|
+
* `*atlasLoading`.
|
|
8
|
+
*/
|
|
9
|
+
export class AtlasLoadedDirective extends AtlasToggleDirective {
|
|
10
|
+
source() {
|
|
11
|
+
return this.atlas.isLoaded$;
|
|
12
|
+
}
|
|
13
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasLoadedDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
14
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: AtlasLoadedDirective, isStandalone: true, selector: "[atlasLoaded]", usesInheritance: true, ngImport: i0 });
|
|
15
|
+
}
|
|
16
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasLoadedDirective, decorators: [{
|
|
17
|
+
type: Directive,
|
|
18
|
+
args: [{
|
|
19
|
+
selector: '[atlasLoaded]',
|
|
20
|
+
standalone: true,
|
|
21
|
+
}]
|
|
22
|
+
}] });
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZGVkLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvZGlyZWN0aXZlcy9sb2FkZWQuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFMUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7O0FBRTFEOzs7O0dBSUc7QUFLSCxNQUFNLE9BQU8sb0JBQXFCLFNBQVEsb0JBQW9CO0lBQ3pDLE1BQU07UUFDdkIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztJQUM5QixDQUFDO3dHQUhVLG9CQUFvQjs0RkFBcEIsb0JBQW9COzs0RkFBcEIsb0JBQW9CO2tCQUpoQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxlQUFlO29CQUN6QixVQUFVLEVBQUUsSUFBSTtpQkFDakIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEF0bGFzVG9nZ2xlRGlyZWN0aXZlIH0gZnJvbSAnLi90b2dnbGUuZGlyZWN0aXZlJztcblxuLyoqXG4gKiBgKmF0bGFzTG9hZGVkYCDigJQgcmVuZGVyIHRoZSB0ZW1wbGF0ZSBvbmx5IG9uY2UgdGhlIFNESyBoYXMgZmluaXNoZWQgYm9vdGluZy5cbiAqIFRoZSBBbmd1bGFyIHBlZXIgb2YgUmVhY3QncyBgPEF0bGFzTG9hZGVkPmAsIHRoZSBzeW1tZXRyaWMgcGFydG5lciBvZlxuICogYCphdGxhc0xvYWRpbmdgLlxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbYXRsYXNMb2FkZWRdJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgQXRsYXNMb2FkZWREaXJlY3RpdmUgZXh0ZW5kcyBBdGxhc1RvZ2dsZURpcmVjdGl2ZSB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBzb3VyY2UoKTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuYXRsYXMuaXNMb2FkZWQkO1xuICB9XG59XG4iXX0=
|