@authon/angular 0.1.19 → 0.2.1
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/dist/index.cjs +113 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.js +111 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
AUTHON_CONFIG: () => AUTHON_CONFIG,
|
|
24
24
|
AuthonService: () => AuthonService,
|
|
25
25
|
authGuard: () => authGuard,
|
|
26
|
-
provideAuthon: () => provideAuthon
|
|
26
|
+
provideAuthon: () => provideAuthon,
|
|
27
|
+
renderSocialButtons: () => renderSocialButtons
|
|
27
28
|
});
|
|
28
29
|
module.exports = __toCommonJS(index_exports);
|
|
29
30
|
|
|
@@ -127,11 +128,121 @@ function provideAuthon(config) {
|
|
|
127
128
|
{ provide: "AuthonService", useValue: service }
|
|
128
129
|
];
|
|
129
130
|
}
|
|
131
|
+
|
|
132
|
+
// src/SocialButtons.ts
|
|
133
|
+
var import_shared = require("@authon/shared");
|
|
134
|
+
var import_js2 = require("@authon/js");
|
|
135
|
+
function renderSocialButtons(options) {
|
|
136
|
+
const {
|
|
137
|
+
client,
|
|
138
|
+
container,
|
|
139
|
+
onSuccess,
|
|
140
|
+
onError,
|
|
141
|
+
compact = false,
|
|
142
|
+
gap,
|
|
143
|
+
labels,
|
|
144
|
+
iconSize,
|
|
145
|
+
borderRadius = 10,
|
|
146
|
+
height = 48,
|
|
147
|
+
size = 48
|
|
148
|
+
} = options;
|
|
149
|
+
const resolvedGap = gap ?? (compact ? 12 : 10);
|
|
150
|
+
const resolvedIconSize = iconSize ?? (compact ? 24 : 20);
|
|
151
|
+
let loadingProvider = null;
|
|
152
|
+
let buttons = [];
|
|
153
|
+
const handleClick = async (provider, btn) => {
|
|
154
|
+
if (loadingProvider) return;
|
|
155
|
+
loadingProvider = provider;
|
|
156
|
+
btn.innerHTML = '<span style="display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite"></span>';
|
|
157
|
+
buttons.forEach((b) => b.disabled = true);
|
|
158
|
+
try {
|
|
159
|
+
await client.signInWithOAuth(provider);
|
|
160
|
+
onSuccess?.();
|
|
161
|
+
} catch (e) {
|
|
162
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
163
|
+
onError?.(error);
|
|
164
|
+
} finally {
|
|
165
|
+
loadingProvider = null;
|
|
166
|
+
renderButtons(providers);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
let providers = [];
|
|
170
|
+
function renderButtons(providerList) {
|
|
171
|
+
container.innerHTML = "";
|
|
172
|
+
buttons = [];
|
|
173
|
+
if (!document.getElementById("authon-spin-style")) {
|
|
174
|
+
const style = document.createElement("style");
|
|
175
|
+
style.id = "authon-spin-style";
|
|
176
|
+
style.textContent = "@keyframes authon-spin{to{transform:rotate(360deg)}}";
|
|
177
|
+
document.head.appendChild(style);
|
|
178
|
+
}
|
|
179
|
+
const wrapper = document.createElement("div");
|
|
180
|
+
wrapper.style.display = "flex";
|
|
181
|
+
wrapper.style.gap = `${resolvedGap}px`;
|
|
182
|
+
if (compact) {
|
|
183
|
+
wrapper.style.flexDirection = "row";
|
|
184
|
+
wrapper.style.flexWrap = "wrap";
|
|
185
|
+
wrapper.style.justifyContent = "center";
|
|
186
|
+
} else {
|
|
187
|
+
wrapper.style.flexDirection = "column";
|
|
188
|
+
}
|
|
189
|
+
for (const provider of providerList) {
|
|
190
|
+
const colors = import_shared.PROVIDER_COLORS[provider] || { bg: "#333", text: "#fff" };
|
|
191
|
+
const displayName = import_shared.PROVIDER_DISPLAY_NAMES[provider] || provider;
|
|
192
|
+
const config = (0, import_js2.getProviderButtonConfig)(provider);
|
|
193
|
+
const iconSvg = config.iconSvg.replace(/width="\d+"/, `width="${resolvedIconSize}"`).replace(/height="\d+"/, `height="${resolvedIconSize}"`);
|
|
194
|
+
const needsBorder = colors.bg.toLowerCase() === "#ffffff";
|
|
195
|
+
const btn = document.createElement("button");
|
|
196
|
+
btn.setAttribute("aria-label", `Sign in with ${displayName}`);
|
|
197
|
+
btn.style.display = "flex";
|
|
198
|
+
btn.style.alignItems = "center";
|
|
199
|
+
btn.style.justifyContent = "center";
|
|
200
|
+
btn.style.border = needsBorder ? "1px solid #dadce0" : "none";
|
|
201
|
+
btn.style.cursor = "pointer";
|
|
202
|
+
btn.style.backgroundColor = colors.bg;
|
|
203
|
+
btn.style.color = colors.text;
|
|
204
|
+
btn.style.borderRadius = `${borderRadius}px`;
|
|
205
|
+
btn.style.transition = "opacity 0.15s";
|
|
206
|
+
btn.style.fontFamily = "inherit";
|
|
207
|
+
if (compact) {
|
|
208
|
+
btn.style.width = `${size}px`;
|
|
209
|
+
btn.style.height = `${size}px`;
|
|
210
|
+
btn.style.padding = "0";
|
|
211
|
+
btn.innerHTML = `<span style="display:flex;align-items:center">${iconSvg}</span>`;
|
|
212
|
+
} else {
|
|
213
|
+
btn.style.width = "100%";
|
|
214
|
+
btn.style.height = `${height}px`;
|
|
215
|
+
btn.style.gap = "10px";
|
|
216
|
+
btn.style.paddingLeft = "16px";
|
|
217
|
+
btn.style.paddingRight = "16px";
|
|
218
|
+
const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;
|
|
219
|
+
btn.innerHTML = `<span style="display:flex;align-items:center;flex-shrink:0">${iconSvg}</span><span style="font-size:15px;font-weight:600;white-space:nowrap">${buttonLabel}</span>`;
|
|
220
|
+
}
|
|
221
|
+
btn.addEventListener("click", () => handleClick(provider, btn));
|
|
222
|
+
btn.addEventListener("mouseenter", () => btn.style.opacity = "0.85");
|
|
223
|
+
btn.addEventListener("mouseleave", () => btn.style.opacity = "1");
|
|
224
|
+
buttons.push(btn);
|
|
225
|
+
wrapper.appendChild(btn);
|
|
226
|
+
}
|
|
227
|
+
container.appendChild(wrapper);
|
|
228
|
+
}
|
|
229
|
+
client.getProviders().then((p) => {
|
|
230
|
+
providers = p;
|
|
231
|
+
if (providers.length > 0) {
|
|
232
|
+
renderButtons(providers);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return () => {
|
|
236
|
+
container.innerHTML = "";
|
|
237
|
+
buttons = [];
|
|
238
|
+
};
|
|
239
|
+
}
|
|
130
240
|
// Annotate the CommonJS export names for ESM import in node:
|
|
131
241
|
0 && (module.exports = {
|
|
132
242
|
AUTHON_CONFIG,
|
|
133
243
|
AuthonService,
|
|
134
244
|
authGuard,
|
|
135
|
-
provideAuthon
|
|
245
|
+
provideAuthon,
|
|
246
|
+
renderSocialButtons
|
|
136
247
|
});
|
|
137
248
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/guard.ts","../src/helpers.ts"],"sourcesContent":["export { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\nexport { authGuard } from './guard';\nexport { provideAuthon } from './helpers';\n","import { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\n/**\n * Injection token key for Authon configuration.\n * Used with Angular's InjectionToken.\n */\nexport const AUTHON_CONFIG = 'AUTHON_CONFIG';\n\nexport interface AuthonServiceConfig {\n publishableKey: string;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\n/**\n * Plain class wrapping @authon/js for Angular dependency injection.\n *\n * Since tsup cannot compile Angular decorators, this is a plain class.\n * Users should wrap it in their own injectable service:\n *\n * ```ts\n * import { Injectable } from '@angular/core';\n * import { AuthonService as BaseAuthonService } from '@authon/angular';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthonService extends BaseAuthonService {\n * constructor() {\n * super({ publishableKey: 'pk_live_...' });\n * }\n * }\n * ```\n *\n * Or use the `provideAuthon()` helper for standalone components.\n */\nexport class AuthonService {\n private client: Authon;\n private _user: AuthonUser | null = null;\n private _isSignedIn = false;\n private _isLoading = true;\n private _listeners: Array<() => void> = [];\n\n constructor(config: AuthonServiceConfig) {\n this.client = new Authon(config.publishableKey, config.config);\n\n this.client.on('signedIn', (user) => {\n this._user = user as AuthonUser;\n this._isSignedIn = true;\n this._isLoading = false;\n this.notifyListeners();\n });\n\n this.client.on('signedOut', () => {\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n });\n\n this.client.on('error', () => {\n this._isLoading = false;\n this.notifyListeners();\n });\n\n const existingUser = this.client.getUser();\n if (existingUser) {\n this._user = existingUser as AuthonUser;\n this._isSignedIn = true;\n }\n this._isLoading = false;\n }\n\n get user(): AuthonUser | null {\n return this._user;\n }\n\n get isSignedIn(): boolean {\n return this._isSignedIn;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n async openSignIn(): Promise<void> {\n await this.client.openSignIn();\n }\n\n async openSignUp(): Promise<void> {\n await this.client.openSignUp();\n }\n\n async signOut(): Promise<void> {\n await this.client.signOut();\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n }\n\n getToken(): string | null {\n return this.client.getToken();\n }\n\n getClient(): Authon {\n return this.client;\n }\n\n /**\n * Subscribe to auth state changes.\n * Returns an unsubscribe function.\n */\n onStateChange(callback: () => void): () => void {\n this._listeners.push(callback);\n return () => {\n this._listeners = this._listeners.filter((l) => l !== callback);\n };\n }\n\n destroy(): void {\n this.client.destroy();\n this._listeners = [];\n }\n\n private notifyListeners(): void {\n for (const listener of this._listeners) {\n listener();\n }\n }\n}\n","import type { AuthonService } from './service';\n\n/**\n * Route guard factory for Angular Router (CanActivateFn style).\n *\n * Since tsup can't compile Angular decorators, this returns a plain function.\n * Users wire it up in their route config:\n *\n * ```ts\n * import { inject } from '@angular/core';\n * import { authGuard } from '@authon/angular';\n * import { AuthonService } from './authon.service'; // your injectable wrapper\n *\n * const routes = [\n * {\n * path: 'dashboard',\n * component: DashboardComponent,\n * canActivate: [() => {\n * const authon = inject(AuthonService);\n * return authGuard(authon, '/login');\n * }],\n * },\n * ];\n * ```\n */\nexport function authGuard(\n authonService: AuthonService,\n redirectTo = '/sign-in',\n): boolean | { path: string } {\n if (authonService.isLoading) {\n return false;\n }\n\n if (!authonService.isSignedIn) {\n return { path: redirectTo };\n }\n\n return true;\n}\n","import { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\n\n/**\n * Provider factory for Angular standalone components.\n *\n * Usage in app.config.ts:\n * ```ts\n * import { provideAuthon } from '@authon/angular';\n *\n * export const appConfig = {\n * providers: [\n * ...provideAuthon({ publishableKey: 'pk_live_...' }),\n * ],\n * };\n * ```\n *\n * Then inject in your components:\n * ```ts\n * import { Inject } from '@angular/core';\n * import { AUTHON_CONFIG, AuthonService } from '@authon/angular';\n *\n * constructor(@Inject('AuthonService') private authon: AuthonService) {}\n * ```\n */\nexport function provideAuthon(config: AuthonServiceConfig) {\n const service = new AuthonService(config);\n\n return [\n { provide: AUTHON_CONFIG, useValue: config },\n { provide: 'AuthonService', useValue: service },\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gBAAuB;AAQhB,IAAM,gBAAgB;AA2BtB,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA,QAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAgC,CAAC;AAAA,EAEzC,YAAY,QAA6B;AACvC,SAAK,SAAS,IAAI,iBAAO,OAAO,gBAAgB,OAAO,MAAM;AAE7D,SAAK,OAAO,GAAG,YAAY,CAAC,SAAS;AACnC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,MAAM;AAChC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,SAAS,MAAM;AAC5B,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,UAAM,eAAe,KAAK,OAAO,QAAQ;AACzC,QAAI,cAAc;AAChB,WAAK,QAAQ;AACb,WAAK,cAAc;AAAA,IACrB;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,IAAI,OAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK,OAAO,QAAQ;AAC1B,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,WAA0B;AACxB,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,UAAkC;AAC9C,SAAK,WAAW,KAAK,QAAQ;AAC7B,WAAO,MAAM;AACX,WAAK,aAAa,KAAK,WAAW,OAAO,CAAC,MAAM,MAAM,QAAQ;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AACpB,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,YAAY,KAAK,YAAY;AACtC,eAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACtGO,SAAS,UACd,eACA,aAAa,YACe;AAC5B,MAAI,cAAc,WAAW;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,YAAY;AAC7B,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAEA,SAAO;AACT;;;ACdO,SAAS,cAAc,QAA6B;AACzD,QAAM,UAAU,IAAI,cAAc,MAAM;AAExC,SAAO;AAAA,IACL,EAAE,SAAS,eAAe,UAAU,OAAO;AAAA,IAC3C,EAAE,SAAS,iBAAiB,UAAU,QAAQ;AAAA,EAChD;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/service.ts","../src/guard.ts","../src/helpers.ts","../src/SocialButtons.ts"],"sourcesContent":["export { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\nexport { authGuard } from './guard';\nexport { provideAuthon } from './helpers';\nexport { renderSocialButtons } from './SocialButtons';\nexport type { SocialButtonsConfig } from './SocialButtons';\n","import { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\n/**\n * Injection token key for Authon configuration.\n * Used with Angular's InjectionToken.\n */\nexport const AUTHON_CONFIG = 'AUTHON_CONFIG';\n\nexport interface AuthonServiceConfig {\n publishableKey: string;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\n/**\n * Plain class wrapping @authon/js for Angular dependency injection.\n *\n * Since tsup cannot compile Angular decorators, this is a plain class.\n * Users should wrap it in their own injectable service:\n *\n * ```ts\n * import { Injectable } from '@angular/core';\n * import { AuthonService as BaseAuthonService } from '@authon/angular';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthonService extends BaseAuthonService {\n * constructor() {\n * super({ publishableKey: 'pk_live_...' });\n * }\n * }\n * ```\n *\n * Or use the `provideAuthon()` helper for standalone components.\n */\nexport class AuthonService {\n private client: Authon;\n private _user: AuthonUser | null = null;\n private _isSignedIn = false;\n private _isLoading = true;\n private _listeners: Array<() => void> = [];\n\n constructor(config: AuthonServiceConfig) {\n this.client = new Authon(config.publishableKey, config.config);\n\n this.client.on('signedIn', (user) => {\n this._user = user as AuthonUser;\n this._isSignedIn = true;\n this._isLoading = false;\n this.notifyListeners();\n });\n\n this.client.on('signedOut', () => {\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n });\n\n this.client.on('error', () => {\n this._isLoading = false;\n this.notifyListeners();\n });\n\n const existingUser = this.client.getUser();\n if (existingUser) {\n this._user = existingUser as AuthonUser;\n this._isSignedIn = true;\n }\n this._isLoading = false;\n }\n\n get user(): AuthonUser | null {\n return this._user;\n }\n\n get isSignedIn(): boolean {\n return this._isSignedIn;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n async openSignIn(): Promise<void> {\n await this.client.openSignIn();\n }\n\n async openSignUp(): Promise<void> {\n await this.client.openSignUp();\n }\n\n async signOut(): Promise<void> {\n await this.client.signOut();\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n }\n\n getToken(): string | null {\n return this.client.getToken();\n }\n\n getClient(): Authon {\n return this.client;\n }\n\n /**\n * Subscribe to auth state changes.\n * Returns an unsubscribe function.\n */\n onStateChange(callback: () => void): () => void {\n this._listeners.push(callback);\n return () => {\n this._listeners = this._listeners.filter((l) => l !== callback);\n };\n }\n\n destroy(): void {\n this.client.destroy();\n this._listeners = [];\n }\n\n private notifyListeners(): void {\n for (const listener of this._listeners) {\n listener();\n }\n }\n}\n","import type { AuthonService } from './service';\n\n/**\n * Route guard factory for Angular Router (CanActivateFn style).\n *\n * Since tsup can't compile Angular decorators, this returns a plain function.\n * Users wire it up in their route config:\n *\n * ```ts\n * import { inject } from '@angular/core';\n * import { authGuard } from '@authon/angular';\n * import { AuthonService } from './authon.service'; // your injectable wrapper\n *\n * const routes = [\n * {\n * path: 'dashboard',\n * component: DashboardComponent,\n * canActivate: [() => {\n * const authon = inject(AuthonService);\n * return authGuard(authon, '/login');\n * }],\n * },\n * ];\n * ```\n */\nexport function authGuard(\n authonService: AuthonService,\n redirectTo = '/sign-in',\n): boolean | { path: string } {\n if (authonService.isLoading) {\n return false;\n }\n\n if (!authonService.isSignedIn) {\n return { path: redirectTo };\n }\n\n return true;\n}\n","import { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\n\n/**\n * Provider factory for Angular standalone components.\n *\n * Usage in app.config.ts:\n * ```ts\n * import { provideAuthon } from '@authon/angular';\n *\n * export const appConfig = {\n * providers: [\n * ...provideAuthon({ publishableKey: 'pk_live_...' }),\n * ],\n * };\n * ```\n *\n * Then inject in your components:\n * ```ts\n * import { Inject } from '@angular/core';\n * import { AUTHON_CONFIG, AuthonService } from '@authon/angular';\n *\n * constructor(@Inject('AuthonService') private authon: AuthonService) {}\n * ```\n */\nexport function provideAuthon(config: AuthonServiceConfig) {\n const service = new AuthonService(config);\n\n return [\n { provide: AUTHON_CONFIG, useValue: config },\n { provide: 'AuthonService', useValue: service },\n ];\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsConfig {\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Renders social login buttons into a container element.\n *\n * Usage with Angular:\n * ```ts\n * import { AuthonService } from '@authon/angular';\n * import { renderSocialButtons } from '@authon/angular';\n *\n * @Component({ ... })\n * export class LoginComponent implements AfterViewInit, OnDestroy {\n * @ViewChild('socialContainer') container!: ElementRef;\n * private cleanup?: () => void;\n *\n * constructor(private authon: AuthonService) {}\n *\n * ngAfterViewInit() {\n * this.cleanup = renderSocialButtons({\n * client: this.authon.getClient(),\n * container: this.container.nativeElement,\n * compact: true,\n * onError: (err) => console.error(err),\n * });\n * }\n *\n * ngOnDestroy() {\n * this.cleanup?.();\n * }\n * }\n * ```\n */\nexport function renderSocialButtons(options: {\n client: Authon;\n container: HTMLElement;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n} & SocialButtonsConfig): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,gBAAuB;AAQhB,IAAM,gBAAgB;AA2BtB,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA,QAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAgC,CAAC;AAAA,EAEzC,YAAY,QAA6B;AACvC,SAAK,SAAS,IAAI,iBAAO,OAAO,gBAAgB,OAAO,MAAM;AAE7D,SAAK,OAAO,GAAG,YAAY,CAAC,SAAS;AACnC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,MAAM;AAChC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,SAAS,MAAM;AAC5B,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,UAAM,eAAe,KAAK,OAAO,QAAQ;AACzC,QAAI,cAAc;AAChB,WAAK,QAAQ;AACb,WAAK,cAAc;AAAA,IACrB;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,IAAI,OAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK,OAAO,QAAQ;AAC1B,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,WAA0B;AACxB,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,UAAkC;AAC9C,SAAK,WAAW,KAAK,QAAQ;AAC7B,WAAO,MAAM;AACX,WAAK,aAAa,KAAK,WAAW,OAAO,CAAC,MAAM,MAAM,QAAQ;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AACpB,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,YAAY,KAAK,YAAY;AACtC,eAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACtGO,SAAS,UACd,eACA,aAAa,YACe;AAC5B,MAAI,cAAc,WAAW;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,YAAY;AAC7B,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAEA,SAAO;AACT;;;ACdO,SAAS,cAAc,QAA6B;AACzD,QAAM,UAAU,IAAI,cAAc,MAAM;AAExC,SAAO;AAAA,IACL,EAAE,SAAS,eAAe,UAAU,OAAO;AAAA,IAC3C,EAAE,SAAS,iBAAiB,UAAU,QAAQ;AAAA,EAChD;AACF;;;AC/BA,oBAAgF;AAChF,IAAAA,aAAqD;AAiD9C,SAAS,oBAAoB,SAKC;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,SAAS;AAAA,IACT,OAAO;AAAA,EACT,IAAI;AAEJ,QAAM,cAAc,QAAQ,UAAU,KAAK;AAC3C,QAAM,mBAAmB,aAAa,UAAU,KAAK;AACrD,MAAI,kBAAiC;AACrC,MAAI,UAA+B,CAAC;AAEpC,QAAM,cAAc,OAAO,UAA6B,QAA2B;AACjF,QAAI,gBAAiB;AACrB,sBAAkB;AAClB,QAAI,YAAY;AAChB,YAAQ,QAAQ,CAAC,MAAO,EAAE,WAAW,IAAK;AAE1C,QAAI;AACF,YAAM,OAAO,gBAAgB,QAAQ;AACrC,kBAAY;AAAA,IACd,SAAS,GAAQ;AACf,YAAM,QAAQ,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AAC1D,gBAAU,KAAK;AAAA,IACjB,UAAE;AACA,wBAAkB;AAClB,oBAAc,SAAS;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,YAAiC,CAAC;AAEtC,WAAS,cAAc,cAAmC;AACxD,cAAU,YAAY;AACtB,cAAU,CAAC;AAEX,QAAI,CAAC,SAAS,eAAe,mBAAmB,GAAG;AACjD,YAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,YAAM,KAAK;AACX,YAAM,cAAc;AACpB,eAAS,KAAK,YAAY,KAAK;AAAA,IACjC;AAEA,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,MAAM,UAAU;AACxB,YAAQ,MAAM,MAAM,GAAG,WAAW;AAElC,QAAI,SAAS;AACX,cAAQ,MAAM,gBAAgB;AAC9B,cAAQ,MAAM,WAAW;AACzB,cAAQ,MAAM,iBAAiB;AAAA,IACjC,OAAO;AACL,cAAQ,MAAM,gBAAgB;AAAA,IAChC;AAEA,eAAW,YAAY,cAAc;AACnC,YAAM,SAAS,8BAAgB,QAAQ,KAAK,EAAE,IAAI,QAAQ,MAAM,OAAO;AACvE,YAAM,cAAc,qCAAuB,QAAQ,KAAK;AACxD,YAAM,aAAS,oCAAwB,QAAQ;AAC/C,YAAM,UAAU,OAAO,QACpB,QAAQ,eAAe,UAAU,gBAAgB,GAAG,EACpD,QAAQ,gBAAgB,WAAW,gBAAgB,GAAG;AACzD,YAAM,cAAc,OAAO,GAAG,YAAY,MAAM;AAEhD,YAAM,MAAM,SAAS,cAAc,QAAQ;AAC3C,UAAI,aAAa,cAAc,gBAAgB,WAAW,EAAE;AAC5D,UAAI,MAAM,UAAU;AACpB,UAAI,MAAM,aAAa;AACvB,UAAI,MAAM,iBAAiB;AAC3B,UAAI,MAAM,SAAS,cAAc,sBAAsB;AACvD,UAAI,MAAM,SAAS;AACnB,UAAI,MAAM,kBAAkB,OAAO;AACnC,UAAI,MAAM,QAAQ,OAAO;AACzB,UAAI,MAAM,eAAe,GAAG,YAAY;AACxC,UAAI,MAAM,aAAa;AACvB,UAAI,MAAM,aAAa;AAEvB,UAAI,SAAS;AACX,YAAI,MAAM,QAAQ,GAAG,IAAI;AACzB,YAAI,MAAM,SAAS,GAAG,IAAI;AAC1B,YAAI,MAAM,UAAU;AACpB,YAAI,YAAY,iDAAiD,OAAO;AAAA,MAC1E,OAAO;AACL,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,SAAS,GAAG,MAAM;AAC5B,YAAI,MAAM,MAAM;AAChB,YAAI,MAAM,cAAc;AACxB,YAAI,MAAM,eAAe;AACzB,cAAM,cAAc,SAAS,QAAQ,KAAK,iBAAiB,WAAW;AACtE,YAAI,YAAY,+DAA+D,OAAO,0EAA0E,WAAW;AAAA,MAC7K;AAEA,UAAI,iBAAiB,SAAS,MAAM,YAAY,UAAU,GAAG,CAAC;AAC9D,UAAI,iBAAiB,cAAc,MAAO,IAAI,MAAM,UAAU,MAAO;AACrE,UAAI,iBAAiB,cAAc,MAAO,IAAI,MAAM,UAAU,GAAI;AAElE,cAAQ,KAAK,GAAG;AAChB,cAAQ,YAAY,GAAG;AAAA,IACzB;AAEA,cAAU,YAAY,OAAO;AAAA,EAC/B;AAEA,SAAO,aAAa,EAAE,KAAK,CAAC,MAA2B;AACrD,gBAAY;AACZ,QAAI,UAAU,SAAS,GAAG;AACxB,oBAAc,SAAS;AAAA,IACzB;AAAA,EACF,CAAC;AAED,SAAO,MAAM;AACX,cAAU,YAAY;AACtB,cAAU,CAAC;AAAA,EACb;AACF;","names":["import_js"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AuthonConfig, Authon } from '@authon/js';
|
|
2
|
-
import { AuthonUser } from '@authon/shared';
|
|
2
|
+
import { AuthonUser, OAuthProviderType } from '@authon/shared';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Injection token key for Authon configuration.
|
|
@@ -111,4 +111,57 @@ declare function provideAuthon(config: AuthonServiceConfig): ({
|
|
|
111
111
|
useValue: AuthonService;
|
|
112
112
|
})[];
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
interface SocialButtonsConfig {
|
|
115
|
+
/** Compact mode — icon-only square buttons in a row (default: false) */
|
|
116
|
+
compact?: boolean;
|
|
117
|
+
/** Gap between buttons in px (default: 10, compact default: 12) */
|
|
118
|
+
gap?: number;
|
|
119
|
+
/** Custom labels per provider */
|
|
120
|
+
labels?: Partial<Record<OAuthProviderType, string>>;
|
|
121
|
+
/** Icon size (default: 20, compact default: 24) */
|
|
122
|
+
iconSize?: number;
|
|
123
|
+
/** Border radius in px (default: 10) */
|
|
124
|
+
borderRadius?: number;
|
|
125
|
+
/** Button height in px (default: 48) */
|
|
126
|
+
height?: number;
|
|
127
|
+
/** Button size for compact mode in px (default: 48) */
|
|
128
|
+
size?: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Renders social login buttons into a container element.
|
|
132
|
+
*
|
|
133
|
+
* Usage with Angular:
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { AuthonService } from '@authon/angular';
|
|
136
|
+
* import { renderSocialButtons } from '@authon/angular';
|
|
137
|
+
*
|
|
138
|
+
* @Component({ ... })
|
|
139
|
+
* export class LoginComponent implements AfterViewInit, OnDestroy {
|
|
140
|
+
* @ViewChild('socialContainer') container!: ElementRef;
|
|
141
|
+
* private cleanup?: () => void;
|
|
142
|
+
*
|
|
143
|
+
* constructor(private authon: AuthonService) {}
|
|
144
|
+
*
|
|
145
|
+
* ngAfterViewInit() {
|
|
146
|
+
* this.cleanup = renderSocialButtons({
|
|
147
|
+
* client: this.authon.getClient(),
|
|
148
|
+
* container: this.container.nativeElement,
|
|
149
|
+
* compact: true,
|
|
150
|
+
* onError: (err) => console.error(err),
|
|
151
|
+
* });
|
|
152
|
+
* }
|
|
153
|
+
*
|
|
154
|
+
* ngOnDestroy() {
|
|
155
|
+
* this.cleanup?.();
|
|
156
|
+
* }
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
declare function renderSocialButtons(options: {
|
|
161
|
+
client: Authon;
|
|
162
|
+
container: HTMLElement;
|
|
163
|
+
onSuccess?: () => void;
|
|
164
|
+
onError?: (error: Error) => void;
|
|
165
|
+
} & SocialButtonsConfig): () => void;
|
|
166
|
+
|
|
167
|
+
export { AUTHON_CONFIG, AuthonService, type AuthonServiceConfig, type SocialButtonsConfig, authGuard, provideAuthon, renderSocialButtons };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AuthonConfig, Authon } from '@authon/js';
|
|
2
|
-
import { AuthonUser } from '@authon/shared';
|
|
2
|
+
import { AuthonUser, OAuthProviderType } from '@authon/shared';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Injection token key for Authon configuration.
|
|
@@ -111,4 +111,57 @@ declare function provideAuthon(config: AuthonServiceConfig): ({
|
|
|
111
111
|
useValue: AuthonService;
|
|
112
112
|
})[];
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
interface SocialButtonsConfig {
|
|
115
|
+
/** Compact mode — icon-only square buttons in a row (default: false) */
|
|
116
|
+
compact?: boolean;
|
|
117
|
+
/** Gap between buttons in px (default: 10, compact default: 12) */
|
|
118
|
+
gap?: number;
|
|
119
|
+
/** Custom labels per provider */
|
|
120
|
+
labels?: Partial<Record<OAuthProviderType, string>>;
|
|
121
|
+
/** Icon size (default: 20, compact default: 24) */
|
|
122
|
+
iconSize?: number;
|
|
123
|
+
/** Border radius in px (default: 10) */
|
|
124
|
+
borderRadius?: number;
|
|
125
|
+
/** Button height in px (default: 48) */
|
|
126
|
+
height?: number;
|
|
127
|
+
/** Button size for compact mode in px (default: 48) */
|
|
128
|
+
size?: number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Renders social login buttons into a container element.
|
|
132
|
+
*
|
|
133
|
+
* Usage with Angular:
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { AuthonService } from '@authon/angular';
|
|
136
|
+
* import { renderSocialButtons } from '@authon/angular';
|
|
137
|
+
*
|
|
138
|
+
* @Component({ ... })
|
|
139
|
+
* export class LoginComponent implements AfterViewInit, OnDestroy {
|
|
140
|
+
* @ViewChild('socialContainer') container!: ElementRef;
|
|
141
|
+
* private cleanup?: () => void;
|
|
142
|
+
*
|
|
143
|
+
* constructor(private authon: AuthonService) {}
|
|
144
|
+
*
|
|
145
|
+
* ngAfterViewInit() {
|
|
146
|
+
* this.cleanup = renderSocialButtons({
|
|
147
|
+
* client: this.authon.getClient(),
|
|
148
|
+
* container: this.container.nativeElement,
|
|
149
|
+
* compact: true,
|
|
150
|
+
* onError: (err) => console.error(err),
|
|
151
|
+
* });
|
|
152
|
+
* }
|
|
153
|
+
*
|
|
154
|
+
* ngOnDestroy() {
|
|
155
|
+
* this.cleanup?.();
|
|
156
|
+
* }
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
declare function renderSocialButtons(options: {
|
|
161
|
+
client: Authon;
|
|
162
|
+
container: HTMLElement;
|
|
163
|
+
onSuccess?: () => void;
|
|
164
|
+
onError?: (error: Error) => void;
|
|
165
|
+
} & SocialButtonsConfig): () => void;
|
|
166
|
+
|
|
167
|
+
export { AUTHON_CONFIG, AuthonService, type AuthonServiceConfig, type SocialButtonsConfig, authGuard, provideAuthon, renderSocialButtons };
|
package/dist/index.js
CHANGED
|
@@ -98,10 +98,120 @@ function provideAuthon(config) {
|
|
|
98
98
|
{ provide: "AuthonService", useValue: service }
|
|
99
99
|
];
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
// src/SocialButtons.ts
|
|
103
|
+
import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES } from "@authon/shared";
|
|
104
|
+
import { getProviderButtonConfig } from "@authon/js";
|
|
105
|
+
function renderSocialButtons(options) {
|
|
106
|
+
const {
|
|
107
|
+
client,
|
|
108
|
+
container,
|
|
109
|
+
onSuccess,
|
|
110
|
+
onError,
|
|
111
|
+
compact = false,
|
|
112
|
+
gap,
|
|
113
|
+
labels,
|
|
114
|
+
iconSize,
|
|
115
|
+
borderRadius = 10,
|
|
116
|
+
height = 48,
|
|
117
|
+
size = 48
|
|
118
|
+
} = options;
|
|
119
|
+
const resolvedGap = gap ?? (compact ? 12 : 10);
|
|
120
|
+
const resolvedIconSize = iconSize ?? (compact ? 24 : 20);
|
|
121
|
+
let loadingProvider = null;
|
|
122
|
+
let buttons = [];
|
|
123
|
+
const handleClick = async (provider, btn) => {
|
|
124
|
+
if (loadingProvider) return;
|
|
125
|
+
loadingProvider = provider;
|
|
126
|
+
btn.innerHTML = '<span style="display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite"></span>';
|
|
127
|
+
buttons.forEach((b) => b.disabled = true);
|
|
128
|
+
try {
|
|
129
|
+
await client.signInWithOAuth(provider);
|
|
130
|
+
onSuccess?.();
|
|
131
|
+
} catch (e) {
|
|
132
|
+
const error = e instanceof Error ? e : new Error(String(e));
|
|
133
|
+
onError?.(error);
|
|
134
|
+
} finally {
|
|
135
|
+
loadingProvider = null;
|
|
136
|
+
renderButtons(providers);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
let providers = [];
|
|
140
|
+
function renderButtons(providerList) {
|
|
141
|
+
container.innerHTML = "";
|
|
142
|
+
buttons = [];
|
|
143
|
+
if (!document.getElementById("authon-spin-style")) {
|
|
144
|
+
const style = document.createElement("style");
|
|
145
|
+
style.id = "authon-spin-style";
|
|
146
|
+
style.textContent = "@keyframes authon-spin{to{transform:rotate(360deg)}}";
|
|
147
|
+
document.head.appendChild(style);
|
|
148
|
+
}
|
|
149
|
+
const wrapper = document.createElement("div");
|
|
150
|
+
wrapper.style.display = "flex";
|
|
151
|
+
wrapper.style.gap = `${resolvedGap}px`;
|
|
152
|
+
if (compact) {
|
|
153
|
+
wrapper.style.flexDirection = "row";
|
|
154
|
+
wrapper.style.flexWrap = "wrap";
|
|
155
|
+
wrapper.style.justifyContent = "center";
|
|
156
|
+
} else {
|
|
157
|
+
wrapper.style.flexDirection = "column";
|
|
158
|
+
}
|
|
159
|
+
for (const provider of providerList) {
|
|
160
|
+
const colors = PROVIDER_COLORS[provider] || { bg: "#333", text: "#fff" };
|
|
161
|
+
const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;
|
|
162
|
+
const config = getProviderButtonConfig(provider);
|
|
163
|
+
const iconSvg = config.iconSvg.replace(/width="\d+"/, `width="${resolvedIconSize}"`).replace(/height="\d+"/, `height="${resolvedIconSize}"`);
|
|
164
|
+
const needsBorder = colors.bg.toLowerCase() === "#ffffff";
|
|
165
|
+
const btn = document.createElement("button");
|
|
166
|
+
btn.setAttribute("aria-label", `Sign in with ${displayName}`);
|
|
167
|
+
btn.style.display = "flex";
|
|
168
|
+
btn.style.alignItems = "center";
|
|
169
|
+
btn.style.justifyContent = "center";
|
|
170
|
+
btn.style.border = needsBorder ? "1px solid #dadce0" : "none";
|
|
171
|
+
btn.style.cursor = "pointer";
|
|
172
|
+
btn.style.backgroundColor = colors.bg;
|
|
173
|
+
btn.style.color = colors.text;
|
|
174
|
+
btn.style.borderRadius = `${borderRadius}px`;
|
|
175
|
+
btn.style.transition = "opacity 0.15s";
|
|
176
|
+
btn.style.fontFamily = "inherit";
|
|
177
|
+
if (compact) {
|
|
178
|
+
btn.style.width = `${size}px`;
|
|
179
|
+
btn.style.height = `${size}px`;
|
|
180
|
+
btn.style.padding = "0";
|
|
181
|
+
btn.innerHTML = `<span style="display:flex;align-items:center">${iconSvg}</span>`;
|
|
182
|
+
} else {
|
|
183
|
+
btn.style.width = "100%";
|
|
184
|
+
btn.style.height = `${height}px`;
|
|
185
|
+
btn.style.gap = "10px";
|
|
186
|
+
btn.style.paddingLeft = "16px";
|
|
187
|
+
btn.style.paddingRight = "16px";
|
|
188
|
+
const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;
|
|
189
|
+
btn.innerHTML = `<span style="display:flex;align-items:center;flex-shrink:0">${iconSvg}</span><span style="font-size:15px;font-weight:600;white-space:nowrap">${buttonLabel}</span>`;
|
|
190
|
+
}
|
|
191
|
+
btn.addEventListener("click", () => handleClick(provider, btn));
|
|
192
|
+
btn.addEventListener("mouseenter", () => btn.style.opacity = "0.85");
|
|
193
|
+
btn.addEventListener("mouseleave", () => btn.style.opacity = "1");
|
|
194
|
+
buttons.push(btn);
|
|
195
|
+
wrapper.appendChild(btn);
|
|
196
|
+
}
|
|
197
|
+
container.appendChild(wrapper);
|
|
198
|
+
}
|
|
199
|
+
client.getProviders().then((p) => {
|
|
200
|
+
providers = p;
|
|
201
|
+
if (providers.length > 0) {
|
|
202
|
+
renderButtons(providers);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
return () => {
|
|
206
|
+
container.innerHTML = "";
|
|
207
|
+
buttons = [];
|
|
208
|
+
};
|
|
209
|
+
}
|
|
101
210
|
export {
|
|
102
211
|
AUTHON_CONFIG,
|
|
103
212
|
AuthonService,
|
|
104
213
|
authGuard,
|
|
105
|
-
provideAuthon
|
|
214
|
+
provideAuthon,
|
|
215
|
+
renderSocialButtons
|
|
106
216
|
};
|
|
107
217
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/service.ts","../src/guard.ts","../src/helpers.ts"],"sourcesContent":["import { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\n/**\n * Injection token key for Authon configuration.\n * Used with Angular's InjectionToken.\n */\nexport const AUTHON_CONFIG = 'AUTHON_CONFIG';\n\nexport interface AuthonServiceConfig {\n publishableKey: string;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\n/**\n * Plain class wrapping @authon/js for Angular dependency injection.\n *\n * Since tsup cannot compile Angular decorators, this is a plain class.\n * Users should wrap it in their own injectable service:\n *\n * ```ts\n * import { Injectable } from '@angular/core';\n * import { AuthonService as BaseAuthonService } from '@authon/angular';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthonService extends BaseAuthonService {\n * constructor() {\n * super({ publishableKey: 'pk_live_...' });\n * }\n * }\n * ```\n *\n * Or use the `provideAuthon()` helper for standalone components.\n */\nexport class AuthonService {\n private client: Authon;\n private _user: AuthonUser | null = null;\n private _isSignedIn = false;\n private _isLoading = true;\n private _listeners: Array<() => void> = [];\n\n constructor(config: AuthonServiceConfig) {\n this.client = new Authon(config.publishableKey, config.config);\n\n this.client.on('signedIn', (user) => {\n this._user = user as AuthonUser;\n this._isSignedIn = true;\n this._isLoading = false;\n this.notifyListeners();\n });\n\n this.client.on('signedOut', () => {\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n });\n\n this.client.on('error', () => {\n this._isLoading = false;\n this.notifyListeners();\n });\n\n const existingUser = this.client.getUser();\n if (existingUser) {\n this._user = existingUser as AuthonUser;\n this._isSignedIn = true;\n }\n this._isLoading = false;\n }\n\n get user(): AuthonUser | null {\n return this._user;\n }\n\n get isSignedIn(): boolean {\n return this._isSignedIn;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n async openSignIn(): Promise<void> {\n await this.client.openSignIn();\n }\n\n async openSignUp(): Promise<void> {\n await this.client.openSignUp();\n }\n\n async signOut(): Promise<void> {\n await this.client.signOut();\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n }\n\n getToken(): string | null {\n return this.client.getToken();\n }\n\n getClient(): Authon {\n return this.client;\n }\n\n /**\n * Subscribe to auth state changes.\n * Returns an unsubscribe function.\n */\n onStateChange(callback: () => void): () => void {\n this._listeners.push(callback);\n return () => {\n this._listeners = this._listeners.filter((l) => l !== callback);\n };\n }\n\n destroy(): void {\n this.client.destroy();\n this._listeners = [];\n }\n\n private notifyListeners(): void {\n for (const listener of this._listeners) {\n listener();\n }\n }\n}\n","import type { AuthonService } from './service';\n\n/**\n * Route guard factory for Angular Router (CanActivateFn style).\n *\n * Since tsup can't compile Angular decorators, this returns a plain function.\n * Users wire it up in their route config:\n *\n * ```ts\n * import { inject } from '@angular/core';\n * import { authGuard } from '@authon/angular';\n * import { AuthonService } from './authon.service'; // your injectable wrapper\n *\n * const routes = [\n * {\n * path: 'dashboard',\n * component: DashboardComponent,\n * canActivate: [() => {\n * const authon = inject(AuthonService);\n * return authGuard(authon, '/login');\n * }],\n * },\n * ];\n * ```\n */\nexport function authGuard(\n authonService: AuthonService,\n redirectTo = '/sign-in',\n): boolean | { path: string } {\n if (authonService.isLoading) {\n return false;\n }\n\n if (!authonService.isSignedIn) {\n return { path: redirectTo };\n }\n\n return true;\n}\n","import { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\n\n/**\n * Provider factory for Angular standalone components.\n *\n * Usage in app.config.ts:\n * ```ts\n * import { provideAuthon } from '@authon/angular';\n *\n * export const appConfig = {\n * providers: [\n * ...provideAuthon({ publishableKey: 'pk_live_...' }),\n * ],\n * };\n * ```\n *\n * Then inject in your components:\n * ```ts\n * import { Inject } from '@angular/core';\n * import { AUTHON_CONFIG, AuthonService } from '@authon/angular';\n *\n * constructor(@Inject('AuthonService') private authon: AuthonService) {}\n * ```\n */\nexport function provideAuthon(config: AuthonServiceConfig) {\n const service = new AuthonService(config);\n\n return [\n { provide: AUTHON_CONFIG, useValue: config },\n { provide: 'AuthonService', useValue: service },\n ];\n}\n"],"mappings":";AAAA,SAAS,cAAc;AAQhB,IAAM,gBAAgB;AA2BtB,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EACA,QAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAgC,CAAC;AAAA,EAEzC,YAAY,QAA6B;AACvC,SAAK,SAAS,IAAI,OAAO,OAAO,gBAAgB,OAAO,MAAM;AAE7D,SAAK,OAAO,GAAG,YAAY,CAAC,SAAS;AACnC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,MAAM;AAChC,WAAK,QAAQ;AACb,WAAK,cAAc;AACnB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,SAAK,OAAO,GAAG,SAAS,MAAM;AAC5B,WAAK,aAAa;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAED,UAAM,eAAe,KAAK,OAAO,QAAQ;AACzC,QAAI,cAAc;AAChB,WAAK,QAAQ;AACb,WAAK,cAAc;AAAA,IACrB;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,IAAI,OAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,OAAO,WAAW;AAAA,EAC/B;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK,OAAO,QAAQ;AAC1B,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,WAA0B;AACxB,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,UAAkC;AAC9C,SAAK,WAAW,KAAK,QAAQ;AAC7B,WAAO,MAAM;AACX,WAAK,aAAa,KAAK,WAAW,OAAO,CAAC,MAAM,MAAM,QAAQ;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AACpB,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,YAAY,KAAK,YAAY;AACtC,eAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACtGO,SAAS,UACd,eACA,aAAa,YACe;AAC5B,MAAI,cAAc,WAAW;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,cAAc,YAAY;AAC7B,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAEA,SAAO;AACT;;;ACdO,SAAS,cAAc,QAA6B;AACzD,QAAM,UAAU,IAAI,cAAc,MAAM;AAExC,SAAO;AAAA,IACL,EAAE,SAAS,eAAe,UAAU,OAAO;AAAA,IAC3C,EAAE,SAAS,iBAAiB,UAAU,QAAQ;AAAA,EAChD;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/service.ts","../src/guard.ts","../src/helpers.ts","../src/SocialButtons.ts"],"sourcesContent":["import { Authon } from '@authon/js';\nimport type { AuthonConfig } from '@authon/js';\nimport type { AuthonUser } from '@authon/shared';\n\n/**\n * Injection token key for Authon configuration.\n * Used with Angular's InjectionToken.\n */\nexport const AUTHON_CONFIG = 'AUTHON_CONFIG';\n\nexport interface AuthonServiceConfig {\n publishableKey: string;\n config?: Omit<AuthonConfig, 'mode'>;\n}\n\n/**\n * Plain class wrapping @authon/js for Angular dependency injection.\n *\n * Since tsup cannot compile Angular decorators, this is a plain class.\n * Users should wrap it in their own injectable service:\n *\n * ```ts\n * import { Injectable } from '@angular/core';\n * import { AuthonService as BaseAuthonService } from '@authon/angular';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthonService extends BaseAuthonService {\n * constructor() {\n * super({ publishableKey: 'pk_live_...' });\n * }\n * }\n * ```\n *\n * Or use the `provideAuthon()` helper for standalone components.\n */\nexport class AuthonService {\n private client: Authon;\n private _user: AuthonUser | null = null;\n private _isSignedIn = false;\n private _isLoading = true;\n private _listeners: Array<() => void> = [];\n\n constructor(config: AuthonServiceConfig) {\n this.client = new Authon(config.publishableKey, config.config);\n\n this.client.on('signedIn', (user) => {\n this._user = user as AuthonUser;\n this._isSignedIn = true;\n this._isLoading = false;\n this.notifyListeners();\n });\n\n this.client.on('signedOut', () => {\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n });\n\n this.client.on('error', () => {\n this._isLoading = false;\n this.notifyListeners();\n });\n\n const existingUser = this.client.getUser();\n if (existingUser) {\n this._user = existingUser as AuthonUser;\n this._isSignedIn = true;\n }\n this._isLoading = false;\n }\n\n get user(): AuthonUser | null {\n return this._user;\n }\n\n get isSignedIn(): boolean {\n return this._isSignedIn;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n async openSignIn(): Promise<void> {\n await this.client.openSignIn();\n }\n\n async openSignUp(): Promise<void> {\n await this.client.openSignUp();\n }\n\n async signOut(): Promise<void> {\n await this.client.signOut();\n this._user = null;\n this._isSignedIn = false;\n this.notifyListeners();\n }\n\n getToken(): string | null {\n return this.client.getToken();\n }\n\n getClient(): Authon {\n return this.client;\n }\n\n /**\n * Subscribe to auth state changes.\n * Returns an unsubscribe function.\n */\n onStateChange(callback: () => void): () => void {\n this._listeners.push(callback);\n return () => {\n this._listeners = this._listeners.filter((l) => l !== callback);\n };\n }\n\n destroy(): void {\n this.client.destroy();\n this._listeners = [];\n }\n\n private notifyListeners(): void {\n for (const listener of this._listeners) {\n listener();\n }\n }\n}\n","import type { AuthonService } from './service';\n\n/**\n * Route guard factory for Angular Router (CanActivateFn style).\n *\n * Since tsup can't compile Angular decorators, this returns a plain function.\n * Users wire it up in their route config:\n *\n * ```ts\n * import { inject } from '@angular/core';\n * import { authGuard } from '@authon/angular';\n * import { AuthonService } from './authon.service'; // your injectable wrapper\n *\n * const routes = [\n * {\n * path: 'dashboard',\n * component: DashboardComponent,\n * canActivate: [() => {\n * const authon = inject(AuthonService);\n * return authGuard(authon, '/login');\n * }],\n * },\n * ];\n * ```\n */\nexport function authGuard(\n authonService: AuthonService,\n redirectTo = '/sign-in',\n): boolean | { path: string } {\n if (authonService.isLoading) {\n return false;\n }\n\n if (!authonService.isSignedIn) {\n return { path: redirectTo };\n }\n\n return true;\n}\n","import { AuthonService, AUTHON_CONFIG, type AuthonServiceConfig } from './service';\n\n/**\n * Provider factory for Angular standalone components.\n *\n * Usage in app.config.ts:\n * ```ts\n * import { provideAuthon } from '@authon/angular';\n *\n * export const appConfig = {\n * providers: [\n * ...provideAuthon({ publishableKey: 'pk_live_...' }),\n * ],\n * };\n * ```\n *\n * Then inject in your components:\n * ```ts\n * import { Inject } from '@angular/core';\n * import { AUTHON_CONFIG, AuthonService } from '@authon/angular';\n *\n * constructor(@Inject('AuthonService') private authon: AuthonService) {}\n * ```\n */\nexport function provideAuthon(config: AuthonServiceConfig) {\n const service = new AuthonService(config);\n\n return [\n { provide: AUTHON_CONFIG, useValue: config },\n { provide: 'AuthonService', useValue: service },\n ];\n}\n","import { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { getProviderButtonConfig, type Authon } from '@authon/js';\n\nexport interface SocialButtonsConfig {\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Gap between buttons in px (default: 10, compact default: 12) */\n gap?: number;\n /** Custom labels per provider */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius in px (default: 10) */\n borderRadius?: number;\n /** Button height in px (default: 48) */\n height?: number;\n /** Button size for compact mode in px (default: 48) */\n size?: number;\n}\n\n/**\n * Renders social login buttons into a container element.\n *\n * Usage with Angular:\n * ```ts\n * import { AuthonService } from '@authon/angular';\n * import { renderSocialButtons } from '@authon/angular';\n *\n * @Component({ ... })\n * export class LoginComponent implements AfterViewInit, OnDestroy {\n * @ViewChild('socialContainer') container!: ElementRef;\n * private cleanup?: () => void;\n *\n * constructor(private authon: AuthonService) {}\n *\n * ngAfterViewInit() {\n * this.cleanup = renderSocialButtons({\n * client: this.authon.getClient(),\n * container: this.container.nativeElement,\n * compact: true,\n * onError: (err) => console.error(err),\n * });\n * }\n *\n * ngOnDestroy() {\n * this.cleanup?.();\n * }\n * }\n * ```\n */\nexport function renderSocialButtons(options: {\n client: Authon;\n container: HTMLElement;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n} & SocialButtonsConfig): () => void {\n const {\n client,\n container,\n onSuccess,\n onError,\n compact = false,\n gap,\n labels,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n } = options;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n let loadingProvider: string | null = null;\n let buttons: HTMLButtonElement[] = [];\n\n const handleClick = async (provider: OAuthProviderType, btn: HTMLButtonElement) => {\n if (loadingProvider) return;\n loadingProvider = provider;\n btn.innerHTML = '<span style=\"display:inline-block;width:16px;height:16px;border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:authon-spin 0.6s linear infinite\"></span>';\n buttons.forEach((b) => (b.disabled = true));\n\n try {\n await client.signInWithOAuth(provider);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n loadingProvider = null;\n renderButtons(providers);\n }\n };\n\n let providers: OAuthProviderType[] = [];\n\n function renderButtons(providerList: OAuthProviderType[]) {\n container.innerHTML = '';\n buttons = [];\n\n if (!document.getElementById('authon-spin-style')) {\n const style = document.createElement('style');\n style.id = 'authon-spin-style';\n style.textContent = '@keyframes authon-spin{to{transform:rotate(360deg)}}';\n document.head.appendChild(style);\n }\n\n const wrapper = document.createElement('div');\n wrapper.style.display = 'flex';\n wrapper.style.gap = `${resolvedGap}px`;\n\n if (compact) {\n wrapper.style.flexDirection = 'row';\n wrapper.style.flexWrap = 'wrap';\n wrapper.style.justifyContent = 'center';\n } else {\n wrapper.style.flexDirection = 'column';\n }\n\n for (const provider of providerList) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const config = getProviderButtonConfig(provider);\n const iconSvg = config.iconSvg\n .replace(/width=\"\\d+\"/, `width=\"${resolvedIconSize}\"`)\n .replace(/height=\"\\d+\"/, `height=\"${resolvedIconSize}\"`);\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n\n const btn = document.createElement('button');\n btn.setAttribute('aria-label', `Sign in with ${displayName}`);\n btn.style.display = 'flex';\n btn.style.alignItems = 'center';\n btn.style.justifyContent = 'center';\n btn.style.border = needsBorder ? '1px solid #dadce0' : 'none';\n btn.style.cursor = 'pointer';\n btn.style.backgroundColor = colors.bg;\n btn.style.color = colors.text;\n btn.style.borderRadius = `${borderRadius}px`;\n btn.style.transition = 'opacity 0.15s';\n btn.style.fontFamily = 'inherit';\n\n if (compact) {\n btn.style.width = `${size}px`;\n btn.style.height = `${size}px`;\n btn.style.padding = '0';\n btn.innerHTML = `<span style=\"display:flex;align-items:center\">${iconSvg}</span>`;\n } else {\n btn.style.width = '100%';\n btn.style.height = `${height}px`;\n btn.style.gap = '10px';\n btn.style.paddingLeft = '16px';\n btn.style.paddingRight = '16px';\n const buttonLabel = labels?.[provider] ?? `Continue with ${displayName}`;\n btn.innerHTML = `<span style=\"display:flex;align-items:center;flex-shrink:0\">${iconSvg}</span><span style=\"font-size:15px;font-weight:600;white-space:nowrap\">${buttonLabel}</span>`;\n }\n\n btn.addEventListener('click', () => handleClick(provider, btn));\n btn.addEventListener('mouseenter', () => (btn.style.opacity = '0.85'));\n btn.addEventListener('mouseleave', () => (btn.style.opacity = '1'));\n\n buttons.push(btn);\n wrapper.appendChild(btn);\n }\n\n container.appendChild(wrapper);\n }\n\n client.getProviders().then((p: OAuthProviderType[]) => {\n providers = p;\n if (providers.length > 0) {\n renderButtons(providers);\n }\n });\n\n return () => {\n container.innerHTML = '';\n buttons = [];\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@authon/angular",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Authon Angular SDK — service, guard, and components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"guard"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@authon/js": "
|
|
41
|
-
"@authon/shared": "
|
|
40
|
+
"@authon/js": "^0.2.1",
|
|
41
|
+
"@authon/shared": "^0.2.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0"
|