@ngx-rock/yandex-smart-captcha 17.0.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/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @ngx-rock/yandex-smart-captcha
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Running unit tests
6
+
7
+ Run `nx test @ngx-rock/yandex-smart-captcha` to execute the unit tests.
@@ -0,0 +1,363 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, viewChild, signal, effect, PLATFORM_ID, forwardRef, Inject, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
4
+ import { isPlatformBrowser, DOCUMENT } from '@angular/common';
5
+
6
+ const domainRE = /^(\S+)$/;
7
+ const localhostDomainRE = /^localhost[:?\d]*(?:[^:?\d]\S*)?$/;
8
+ const nonLocalhostDomainRE = /^[^\s.]+\.\S{2,}$/;
9
+ const IPv4RE = /^(https?:\/\/)?([0-9]{1,3}\.){3}[0-9]{1,3}:\d+$/;
10
+ const IPv6RE = /^(https?:\/\/)?\[([0-9a-fA-F]{0,4}:){7}([0-9a-fA-F]){0,4}]:\d+$/;
11
+ function isValidHost(str) {
12
+ if (typeof str !== 'string') {
13
+ return false;
14
+ }
15
+ const match = str.match(domainRE);
16
+ if (!match) {
17
+ return false;
18
+ }
19
+ const everythingAfterProtocol = match[0];
20
+ if (!everythingAfterProtocol) {
21
+ return false;
22
+ }
23
+ return (localhostDomainRE.test(everythingAfterProtocol) ||
24
+ nonLocalhostDomainRE.test(everythingAfterProtocol) ||
25
+ IPv4RE.test(everythingAfterProtocol) ||
26
+ IPv6RE.test(everythingAfterProtocol));
27
+ }
28
+
29
+ const API_LINK = (host = 'smartcaptcha.yandexcloud.net') => {
30
+ const base = /^https?/.test(host) ? host : `https://${host}`;
31
+ return `${base}/captcha.js?render=onload&onload=__onSmartCaptchaReady`;
32
+ };
33
+ // Shared callbacks array
34
+ const callbacks = [];
35
+ const startLoading = new Map();
36
+ class SmartCaptchaComponent {
37
+ renderer2;
38
+ document;
39
+ platformId;
40
+ sitekey = input.required();
41
+ invisible = input(false);
42
+ visible = input(); // For InvisibleCaptcha to execute
43
+ hideShield = input();
44
+ shieldPosition = input();
45
+ language = input();
46
+ host = input();
47
+ theme = input('auto');
48
+ test = input();
49
+ webview = input();
50
+ challengeHidden = output();
51
+ challengeVisible = output();
52
+ success = output();
53
+ networkError = output();
54
+ tokenExpired = output();
55
+ javascriptError = output();
56
+ captchaContainer = viewChild('captchaContainer');
57
+ widgetId;
58
+ smartCaptchaInstance;
59
+ destroyed = false;
60
+ unsubscribeFns = [];
61
+ errorEventHandler;
62
+ onChange = () => {
63
+ // onChange
64
+ };
65
+ onTouched = () => {
66
+ // onTouched
67
+ };
68
+ _innerValue = signal(null); // Use a signal for innerValue
69
+ callbackIndex = null;
70
+ constructor(renderer2, document, platformId) {
71
+ this.renderer2 = renderer2;
72
+ this.document = document;
73
+ this.platformId = platformId;
74
+ // Effect for theme changes
75
+ effect(() => {
76
+ if (this.theme() &&
77
+ this.widgetId !== undefined &&
78
+ this.smartCaptchaInstance?.setTheme) {
79
+ this.smartCaptchaInstance.setTheme(this.widgetId, this.theme());
80
+ }
81
+ });
82
+ // Effect for visible changes (Invisible Captcha)
83
+ effect(() => {
84
+ if (this.visible() &&
85
+ this.invisible() &&
86
+ this.smartCaptchaInstance &&
87
+ typeof this.widgetId === 'number' &&
88
+ !this.destroyed) {
89
+ this.smartCaptchaInstance.execute(this.widgetId);
90
+ }
91
+ });
92
+ }
93
+ ngOnInit() {
94
+ if (!isPlatformBrowser(this.platformId)) {
95
+ return; // Don't proceed on server-side
96
+ }
97
+ if (this.host() !== undefined && !isValidHost(this.host())) {
98
+ console.error(`[SmartCaptcha] ${this.host()} host is invalid. It should be of a kind: domain.ru, localhost:3000`);
99
+ return;
100
+ }
101
+ if (typeof window !== 'undefined') {
102
+ // Setup global callback if not already defined
103
+ if (window.__onSmartCaptchaReady === undefined) {
104
+ window.__onSmartCaptchaReady = () => {
105
+ callbacks.forEach((callback) => callback());
106
+ };
107
+ }
108
+ // Check if SmartCaptcha is already loaded
109
+ if (window.smartCaptcha) {
110
+ this.smartCaptchaInstance = window.smartCaptcha;
111
+ }
112
+ // Add our callback to the shared array
113
+ this.callbackIndex = callbacks.push(() => {
114
+ this.smartCaptchaInstance = window.smartCaptcha;
115
+ this.renderCaptcha();
116
+ });
117
+ // Load script if not already loading
118
+ const hostKey = this.host() || 'default';
119
+ if (!startLoading.get(hostKey)) {
120
+ this.loadScript();
121
+ startLoading.set(hostKey, true);
122
+ }
123
+ }
124
+ }
125
+ ngAfterViewInit() {
126
+ if (this.smartCaptchaInstance) {
127
+ this.renderCaptcha();
128
+ }
129
+ }
130
+ ngOnDestroy() {
131
+ this.destroyed = true;
132
+ // Remove callback from shared array
133
+ if (this.callbackIndex !== null) {
134
+ callbacks.splice(this.callbackIndex - 1, 1);
135
+ }
136
+ // Destroy widget if it exists
137
+ if (this.widgetId !== undefined && this.smartCaptchaInstance) {
138
+ this.smartCaptchaInstance.destroy(this.widgetId);
139
+ this.widgetId = undefined;
140
+ }
141
+ // Clean up subscriptions
142
+ this.unsubscribeFns.forEach((fn) => fn && fn());
143
+ this.unsubscribeFns = [];
144
+ // Remove error event handler
145
+ if (this.errorEventHandler && typeof window !== 'undefined') {
146
+ window.removeEventListener('error', this.errorEventHandler);
147
+ }
148
+ }
149
+ loadScript() {
150
+ const src = API_LINK(this.host());
151
+ const script = this.renderer2.createElement('script');
152
+ this.renderer2.setAttribute(script, 'src', src);
153
+ this.renderer2.setAttribute(script, 'type', 'text/javascript');
154
+ this.renderer2.setAttribute(script, 'crossOrigin', 'anonymous');
155
+ // Handle regular onload/onerror
156
+ script.onload = () => {
157
+ if (window.smartCaptcha && !this.smartCaptchaInstance) {
158
+ this.smartCaptchaInstance = window.smartCaptcha;
159
+ this.renderCaptcha();
160
+ }
161
+ };
162
+ script.onerror = () => {
163
+ this.handleJavascriptError({
164
+ filename: src,
165
+ message: 'Unknown error on script loading',
166
+ col: 0,
167
+ line: 0,
168
+ });
169
+ };
170
+ // Add error event listener for JS errors in the captcha script
171
+ if (typeof window !== 'undefined') {
172
+ this.errorEventHandler = (e) => {
173
+ if (e.filename?.indexOf(src) === 0) {
174
+ this.handleJavascriptError({
175
+ filename: e.filename,
176
+ message: e.message,
177
+ col: e.colno,
178
+ line: e.lineno,
179
+ });
180
+ }
181
+ };
182
+ window.addEventListener('error', this.errorEventHandler);
183
+ }
184
+ // Add script to document
185
+ this.renderer2.appendChild(this.document.body, script);
186
+ }
187
+ renderCaptcha() {
188
+ const container = this.captchaContainer()?.nativeElement;
189
+ if (!container ||
190
+ !this.smartCaptchaInstance ||
191
+ this.widgetId !== undefined ||
192
+ this.destroyed) {
193
+ return;
194
+ }
195
+ const params = {
196
+ sitekey: this.sitekey(),
197
+ hl: this.language(),
198
+ theme: this.theme(),
199
+ invisible: this.invisible(),
200
+ hideShield: this.hideShield(),
201
+ shieldPosition: this.shieldPosition(),
202
+ test: this.test(),
203
+ webview: this.webview(),
204
+ };
205
+ try {
206
+ this.widgetId = this.smartCaptchaInstance.render(container, params);
207
+ this.setupSubscriptions();
208
+ }
209
+ catch (error) {
210
+ console.error('[SmartCaptcha] Error rendering captcha widget:', error);
211
+ let message = 'Unknown error during rendering';
212
+ if (error instanceof Error) {
213
+ message = error.message;
214
+ }
215
+ this.handleJavascriptError({
216
+ filename: API_LINK(this.host()),
217
+ message,
218
+ col: 0,
219
+ line: 0,
220
+ });
221
+ }
222
+ }
223
+ setupSubscriptions() {
224
+ if (this.widgetId === undefined || !this.smartCaptchaInstance) {
225
+ return;
226
+ }
227
+ // Store unsubscribe functions for cleanup
228
+ this.unsubscribeFns = [
229
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'challenge-visible', () => {
230
+ this.challengeVisible.emit();
231
+ }),
232
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'challenge-hidden', () => {
233
+ console.error('hidden');
234
+ this.challengeHidden.emit();
235
+ }),
236
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'network-error', () => {
237
+ this.networkError.emit();
238
+ }),
239
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'success', (...args) => {
240
+ const [token] = args;
241
+ this._innerValue.set(token);
242
+ this.onChange(token);
243
+ this.onTouched();
244
+ this.success.emit(token);
245
+ }),
246
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'token-expired', () => {
247
+ this._innerValue.set(null);
248
+ this.onChange(null);
249
+ this.onTouched();
250
+ this.tokenExpired.emit();
251
+ }),
252
+ this.smartCaptchaInstance.subscribe(this.widgetId, 'javascript-error', (...args) => {
253
+ const [error] = args;
254
+ this.handleJavascriptError(error);
255
+ }),
256
+ ];
257
+ }
258
+ handleJavascriptError(error) {
259
+ console.error('[SmartCaptcha] Javascript error:', error);
260
+ this.javascriptError.emit(error);
261
+ }
262
+ // ControlValueAccessor methods
263
+ writeValue(value) {
264
+ this._innerValue.set(value); // Set the signal value
265
+ }
266
+ registerOnChange(fn) {
267
+ this.onChange = fn;
268
+ }
269
+ registerOnTouched(fn) {
270
+ this.onTouched = fn;
271
+ }
272
+ // Validator method
273
+ validate() {
274
+ // When using invisible captcha, don't validate until user interacts
275
+ if (this.invisible() && !this._innerValue()) {
276
+ return null;
277
+ }
278
+ // For standard captcha, require token
279
+ if (!this.invisible() && !this._innerValue()) {
280
+ // Access signal value
281
+ return { captchaRequired: true };
282
+ }
283
+ return null;
284
+ }
285
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: SmartCaptchaComponent, deps: [{ token: i0.Renderer2 }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component });
286
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.2", type: SmartCaptchaComponent, isStandalone: true, selector: "smart-captcha", inputs: { sitekey: { classPropertyName: "sitekey", publicName: "sitekey", isSignal: true, isRequired: true, transformFunction: null }, invisible: { classPropertyName: "invisible", publicName: "invisible", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, hideShield: { classPropertyName: "hideShield", publicName: "hideShield", isSignal: true, isRequired: false, transformFunction: null }, shieldPosition: { classPropertyName: "shieldPosition", publicName: "shieldPosition", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, host: { classPropertyName: "host", publicName: "host", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, test: { classPropertyName: "test", publicName: "test", isSignal: true, isRequired: false, transformFunction: null }, webview: { classPropertyName: "webview", publicName: "webview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { challengeHidden: "challengeHidden", challengeVisible: "challengeVisible", success: "success", networkError: "networkError", tokenExpired: "tokenExpired", javascriptError: "javascriptError" }, providers: [
287
+ {
288
+ provide: NG_VALUE_ACCESSOR,
289
+ useExisting: forwardRef(() => SmartCaptchaComponent),
290
+ multi: true,
291
+ },
292
+ {
293
+ provide: NG_VALIDATORS,
294
+ useExisting: forwardRef(() => SmartCaptchaComponent),
295
+ multi: true,
296
+ },
297
+ ], viewQueries: [{ propertyName: "captchaContainer", first: true, predicate: ["captchaContainer"], descendants: true, isSignal: true }], ngImport: i0, template: ` <div class="smart-captcha" #captchaContainer></div> `, isInline: true, styles: [".smart-captcha{height:102px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
298
+ }
299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: SmartCaptchaComponent, decorators: [{
300
+ type: Component,
301
+ args: [{ selector: 'smart-captcha', template: ` <div class="smart-captcha" #captchaContainer></div> `, providers: [
302
+ {
303
+ provide: NG_VALUE_ACCESSOR,
304
+ useExisting: forwardRef(() => SmartCaptchaComponent),
305
+ multi: true,
306
+ },
307
+ {
308
+ provide: NG_VALIDATORS,
309
+ useExisting: forwardRef(() => SmartCaptchaComponent),
310
+ multi: true,
311
+ },
312
+ ], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, styles: [".smart-captcha{height:102px}\n"] }]
313
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: Document, decorators: [{
314
+ type: Inject,
315
+ args: [DOCUMENT]
316
+ }] }, { type: undefined, decorators: [{
317
+ type: Inject,
318
+ args: [PLATFORM_ID]
319
+ }] }] });
320
+ class InvisibleSmartCaptchaComponent extends SmartCaptchaComponent {
321
+ // Always set invisible to true
322
+ invisible = input(true);
323
+ // Override ngOnInit to ensure invisible is always true
324
+ ngOnInit() {
325
+ // Call parent initialization
326
+ super.ngOnInit();
327
+ }
328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: InvisibleSmartCaptchaComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
329
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.2", type: InvisibleSmartCaptchaComponent, isStandalone: true, selector: "invisible-smart-captcha", inputs: { invisible: { classPropertyName: "invisible", publicName: "invisible", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
330
+ {
331
+ provide: NG_VALUE_ACCESSOR,
332
+ useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),
333
+ multi: true,
334
+ },
335
+ {
336
+ provide: NG_VALIDATORS,
337
+ useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),
338
+ multi: true,
339
+ },
340
+ ], usesInheritance: true, ngImport: i0, template: ` <div class="smart-captcha" #captchaContainer></div> `, isInline: true, styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush });
341
+ }
342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.2", ngImport: i0, type: InvisibleSmartCaptchaComponent, decorators: [{
343
+ type: Component,
344
+ args: [{ selector: 'invisible-smart-captcha', template: ` <div class="smart-captcha" #captchaContainer></div> `, providers: [
345
+ {
346
+ provide: NG_VALUE_ACCESSOR,
347
+ useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),
348
+ multi: true,
349
+ },
350
+ {
351
+ provide: NG_VALIDATORS,
352
+ useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),
353
+ multi: true,
354
+ },
355
+ ], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush }]
356
+ }] });
357
+
358
+ /**
359
+ * Generated bundle index. Do not edit.
360
+ */
361
+
362
+ export { InvisibleSmartCaptchaComponent, SmartCaptchaComponent, startLoading };
363
+ //# sourceMappingURL=ngx-rock-yandex-smart-captcha.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-rock-yandex-smart-captcha.mjs","sources":["../../../../libs/yandex-smart-captcha/src/lib/helpers/is-valid-host.ts","../../../../libs/yandex-smart-captcha/src/lib/yandex-smart-captcha/yandex-smart-captcha.component.ts","../../../../libs/yandex-smart-captcha/src/ngx-rock-yandex-smart-captcha.ts"],"sourcesContent":["const domainRE = /^(\\S+)$/;\nconst localhostDomainRE = /^localhost[:?\\d]*(?:[^:?\\d]\\S*)?$/;\nconst nonLocalhostDomainRE = /^[^\\s.]+\\.\\S{2,}$/;\nconst IPv4RE = /^(https?:\\/\\/)?([0-9]{1,3}\\.){3}[0-9]{1,3}:\\d+$/;\nconst IPv6RE =\n /^(https?:\\/\\/)?\\[([0-9a-fA-F]{0,4}:){7}([0-9a-fA-F]){0,4}]:\\d+$/;\n\nexport function isValidHost(str: string | undefined): boolean {\n if (typeof str !== 'string') {\n return false;\n }\n const match = str.match(domainRE);\n if (!match) {\n return false;\n }\n const everythingAfterProtocol = match[0];\n if (!everythingAfterProtocol) {\n return false;\n }\n return (\n localhostDomainRE.test(everythingAfterProtocol) ||\n nonLocalhostDomainRE.test(everythingAfterProtocol) ||\n IPv4RE.test(everythingAfterProtocol) ||\n IPv6RE.test(everythingAfterProtocol)\n );\n}\n","import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n effect,\n ElementRef,\n forwardRef,\n Inject,\n input,\n OnDestroy,\n OnInit,\n output,\n PLATFORM_ID,\n Renderer2,\n signal,\n viewChild,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n NG_VALIDATORS,\n NG_VALUE_ACCESSOR,\n ValidationErrors,\n Validator,\n} from '@angular/forms';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { isValidHost } from '../helpers/is-valid-host';\nimport {\n JavascriptErrorPayload,\n SmartCaptchaInstance,\n SmartCaptchaParams,\n} from '../types';\n\nconst API_LINK = (host = 'smartcaptcha.yandexcloud.net') => {\n const base = /^https?/.test(host) ? host : `https://${host}`;\n return `${base}/captcha.js?render=onload&onload=__onSmartCaptchaReady`;\n};\n\n// Shared callbacks array\nconst callbacks: (() => void)[] = [];\nexport const startLoading = new Map<string, boolean>();\n\n@Component({\n selector: 'smart-captcha',\n template: ` <div class=\"smart-captcha\" #captchaContainer></div> `,\n styles: [\n `\n .smart-captcha {\n height: 102px;\n }\n `,\n ],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => SmartCaptchaComponent),\n multi: true,\n },\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => SmartCaptchaComponent),\n multi: true,\n },\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n})\nexport class SmartCaptchaComponent\n implements ControlValueAccessor, Validator, OnInit, AfterViewInit, OnDestroy\n{\n sitekey = input.required<string>();\n invisible = input<boolean>(false);\n visible = input<boolean>(); // For InvisibleCaptcha to execute\n hideShield = input<boolean>();\n shieldPosition = input<\n 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n >();\n language = input<string>();\n host = input<string>();\n theme = input<'light' | 'dark' | 'auto'>('auto');\n test = input<boolean>();\n webview = input<boolean>();\n\n challengeHidden = output<void>();\n challengeVisible = output<void>();\n success = output<string>();\n networkError = output<void>();\n tokenExpired = output<void>();\n javascriptError = output<JavascriptErrorPayload>();\n\n captchaContainer = viewChild<ElementRef<HTMLDivElement>>('captchaContainer');\n\n protected widgetId: number | undefined;\n protected smartCaptchaInstance: SmartCaptchaInstance | undefined;\n protected destroyed = false;\n private unsubscribeFns: Array<(() => void) | undefined> = [];\n private errorEventHandler: ((e: ErrorEvent) => void) | undefined;\n\n private onChange: (value: string | null) => void = () => {\n // onChange\n };\n private onTouched = () => {\n // onTouched\n };\n private _innerValue = signal<string | null>(null); // Use a signal for innerValue\n private callbackIndex: number | null = null;\n\n constructor(\n private renderer2: Renderer2,\n @Inject(DOCUMENT) private document: Document,\n @Inject(PLATFORM_ID) private platformId: object\n ) {\n // Effect for theme changes\n effect(() => {\n if (\n this.theme() &&\n this.widgetId !== undefined &&\n this.smartCaptchaInstance?.setTheme\n ) {\n this.smartCaptchaInstance.setTheme(this.widgetId, this.theme());\n }\n });\n\n // Effect for visible changes (Invisible Captcha)\n effect(() => {\n if (\n this.visible() &&\n this.invisible() &&\n this.smartCaptchaInstance &&\n typeof this.widgetId === 'number' &&\n !this.destroyed\n ) {\n this.smartCaptchaInstance.execute(this.widgetId);\n }\n });\n }\n\n ngOnInit(): void {\n if (!isPlatformBrowser(this.platformId)) {\n return; // Don't proceed on server-side\n }\n\n if (this.host() !== undefined && !isValidHost(this.host())) {\n console.error(\n `[SmartCaptcha] ${this.host()} host is invalid. It should be of a kind: domain.ru, localhost:3000`\n );\n return;\n }\n\n if (typeof window !== 'undefined') {\n // Setup global callback if not already defined\n if (window.__onSmartCaptchaReady === undefined) {\n window.__onSmartCaptchaReady = () => {\n callbacks.forEach((callback) => callback());\n };\n }\n\n // Check if SmartCaptcha is already loaded\n if (window.smartCaptcha) {\n this.smartCaptchaInstance = window.smartCaptcha;\n }\n\n // Add our callback to the shared array\n this.callbackIndex = callbacks.push(() => {\n this.smartCaptchaInstance = window.smartCaptcha;\n this.renderCaptcha();\n });\n\n // Load script if not already loading\n const hostKey = this.host() || 'default';\n if (!startLoading.get(hostKey)) {\n this.loadScript();\n startLoading.set(hostKey, true);\n }\n }\n }\n\n ngAfterViewInit(): void {\n if (this.smartCaptchaInstance) {\n this.renderCaptcha();\n }\n }\n\n ngOnDestroy(): void {\n this.destroyed = true;\n\n // Remove callback from shared array\n if (this.callbackIndex !== null) {\n callbacks.splice(this.callbackIndex - 1, 1);\n }\n\n // Destroy widget if it exists\n if (this.widgetId !== undefined && this.smartCaptchaInstance) {\n this.smartCaptchaInstance.destroy(this.widgetId);\n this.widgetId = undefined;\n }\n\n // Clean up subscriptions\n this.unsubscribeFns.forEach((fn) => fn && fn());\n this.unsubscribeFns = [];\n\n // Remove error event handler\n if (this.errorEventHandler && typeof window !== 'undefined') {\n window.removeEventListener('error', this.errorEventHandler);\n }\n }\n\n private loadScript(): void {\n const src = API_LINK(this.host());\n const script = this.renderer2.createElement('script');\n this.renderer2.setAttribute(script, 'src', src);\n this.renderer2.setAttribute(script, 'type', 'text/javascript');\n this.renderer2.setAttribute(script, 'crossOrigin', 'anonymous');\n\n // Handle regular onload/onerror\n script.onload = () => {\n if (window.smartCaptcha && !this.smartCaptchaInstance) {\n this.smartCaptchaInstance = window.smartCaptcha;\n this.renderCaptcha();\n }\n };\n\n script.onerror = () => {\n this.handleJavascriptError({\n filename: src,\n message: 'Unknown error on script loading',\n col: 0,\n line: 0,\n });\n };\n\n // Add error event listener for JS errors in the captcha script\n if (typeof window !== 'undefined') {\n this.errorEventHandler = (e: ErrorEvent) => {\n if (e.filename?.indexOf(src) === 0) {\n this.handleJavascriptError({\n filename: e.filename,\n message: e.message,\n col: e.colno,\n line: e.lineno,\n });\n }\n };\n window.addEventListener('error', this.errorEventHandler);\n }\n\n // Add script to document\n this.renderer2.appendChild(this.document.body, script);\n }\n\n private renderCaptcha(): void {\n const container = this.captchaContainer()?.nativeElement;\n if (\n !container ||\n !this.smartCaptchaInstance ||\n this.widgetId !== undefined ||\n this.destroyed\n ) {\n return;\n }\n\n const params: SmartCaptchaParams = {\n sitekey: this.sitekey(),\n hl: this.language(),\n theme: this.theme(),\n invisible: this.invisible(),\n hideShield: this.hideShield(),\n shieldPosition: this.shieldPosition(),\n test: this.test(),\n webview: this.webview(),\n };\n\n try {\n this.widgetId = this.smartCaptchaInstance.render(container, params);\n this.setupSubscriptions();\n } catch (error: unknown) {\n console.error('[SmartCaptcha] Error rendering captcha widget:', error);\n\n let message = 'Unknown error during rendering';\n if (error instanceof Error) {\n message = error.message;\n }\n\n this.handleJavascriptError({\n filename: API_LINK(this.host()),\n message,\n col: 0,\n line: 0,\n });\n }\n }\n\n private setupSubscriptions(): void {\n if (this.widgetId === undefined || !this.smartCaptchaInstance) {\n return;\n }\n\n // Store unsubscribe functions for cleanup\n this.unsubscribeFns = [\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'challenge-visible',\n () => {\n this.challengeVisible.emit();\n }\n ),\n\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'challenge-hidden',\n () => {\n console.error('hidden');\n this.challengeHidden.emit();\n }\n ),\n\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'network-error',\n () => {\n this.networkError.emit();\n }\n ),\n\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'success',\n (...args: unknown[]) => {\n const [token] = args as [string];\n\n this._innerValue.set(token);\n this.onChange(token);\n this.onTouched();\n this.success.emit(token);\n }\n ),\n\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'token-expired',\n () => {\n this._innerValue.set(null);\n this.onChange(null);\n this.onTouched();\n this.tokenExpired.emit();\n }\n ),\n\n this.smartCaptchaInstance.subscribe(\n this.widgetId,\n 'javascript-error',\n (...args: unknown[]) => {\n const [error] = args as [JavascriptErrorPayload];\n this.handleJavascriptError(error);\n }\n ),\n ];\n }\n\n private handleJavascriptError(error: JavascriptErrorPayload): void {\n console.error('[SmartCaptcha] Javascript error:', error);\n this.javascriptError.emit(error);\n }\n\n // ControlValueAccessor methods\n writeValue(value: string): void {\n this._innerValue.set(value); // Set the signal value\n }\n\n registerOnChange(fn: (value: string | null) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n // Validator method\n validate(): ValidationErrors | null {\n // When using invisible captcha, don't validate until user interacts\n if (this.invisible() && !this._innerValue()) {\n return null;\n }\n\n // For standard captcha, require token\n if (!this.invisible() && !this._innerValue()) {\n // Access signal value\n return { captchaRequired: true };\n }\n\n return null;\n }\n}\n\n@Component({\n selector: 'invisible-smart-captcha',\n template: ` <div class=\"smart-captcha\" #captchaContainer></div> `,\n styles: [\n `\n .smart-captcha {\n /* No height needed for invisible captcha */\n }\n `,\n ],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),\n multi: true,\n },\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => InvisibleSmartCaptchaComponent),\n multi: true,\n },\n ],\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class InvisibleSmartCaptchaComponent\n extends SmartCaptchaComponent\n implements OnInit\n{\n // Always set invisible to true\n override invisible = input(true);\n\n // Override ngOnInit to ensure invisible is always true\n override ngOnInit(): void {\n // Call parent initialization\n super.ngOnInit();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './lib/yandex-smart-captcha/yandex-smart-captcha.component';
@@ -0,0 +1 @@
1
+ export declare function isValidHost(str: string | undefined): boolean;
@@ -0,0 +1,56 @@
1
+ import { AfterViewInit, ElementRef, OnDestroy, OnInit, Renderer2 } from '@angular/core';
2
+ import { ControlValueAccessor, ValidationErrors, Validator } from '@angular/forms';
3
+ import { JavascriptErrorPayload, SmartCaptchaInstance } from '../types';
4
+ import * as i0 from "@angular/core";
5
+ export declare const startLoading: Map<string, boolean>;
6
+ export declare class SmartCaptchaComponent implements ControlValueAccessor, Validator, OnInit, AfterViewInit, OnDestroy {
7
+ private renderer2;
8
+ private document;
9
+ private platformId;
10
+ sitekey: import("@angular/core").InputSignal<string>;
11
+ invisible: import("@angular/core").InputSignal<boolean>;
12
+ visible: import("@angular/core").InputSignal<boolean | undefined>;
13
+ hideShield: import("@angular/core").InputSignal<boolean | undefined>;
14
+ shieldPosition: import("@angular/core").InputSignal<"top-left" | "top-right" | "bottom-left" | "bottom-right" | undefined>;
15
+ language: import("@angular/core").InputSignal<string | undefined>;
16
+ host: import("@angular/core").InputSignal<string | undefined>;
17
+ theme: import("@angular/core").InputSignal<"light" | "dark" | "auto">;
18
+ test: import("@angular/core").InputSignal<boolean | undefined>;
19
+ webview: import("@angular/core").InputSignal<boolean | undefined>;
20
+ challengeHidden: import("@angular/core").OutputEmitterRef<void>;
21
+ challengeVisible: import("@angular/core").OutputEmitterRef<void>;
22
+ success: import("@angular/core").OutputEmitterRef<string>;
23
+ networkError: import("@angular/core").OutputEmitterRef<void>;
24
+ tokenExpired: import("@angular/core").OutputEmitterRef<void>;
25
+ javascriptError: import("@angular/core").OutputEmitterRef<JavascriptErrorPayload>;
26
+ captchaContainer: import("@angular/core").Signal<ElementRef<HTMLDivElement> | undefined>;
27
+ protected widgetId: number | undefined;
28
+ protected smartCaptchaInstance: SmartCaptchaInstance | undefined;
29
+ protected destroyed: boolean;
30
+ private unsubscribeFns;
31
+ private errorEventHandler;
32
+ private onChange;
33
+ private onTouched;
34
+ private _innerValue;
35
+ private callbackIndex;
36
+ constructor(renderer2: Renderer2, document: Document, platformId: object);
37
+ ngOnInit(): void;
38
+ ngAfterViewInit(): void;
39
+ ngOnDestroy(): void;
40
+ private loadScript;
41
+ private renderCaptcha;
42
+ private setupSubscriptions;
43
+ private handleJavascriptError;
44
+ writeValue(value: string): void;
45
+ registerOnChange(fn: (value: string | null) => void): void;
46
+ registerOnTouched(fn: () => void): void;
47
+ validate(): ValidationErrors | null;
48
+ static ɵfac: i0.ɵɵFactoryDeclaration<SmartCaptchaComponent, never>;
49
+ static ɵcmp: i0.ɵɵComponentDeclaration<SmartCaptchaComponent, "smart-captcha", never, { "sitekey": { "alias": "sitekey"; "required": true; "isSignal": true; }; "invisible": { "alias": "invisible"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "hideShield": { "alias": "hideShield"; "required": false; "isSignal": true; }; "shieldPosition": { "alias": "shieldPosition"; "required": false; "isSignal": true; }; "language": { "alias": "language"; "required": false; "isSignal": true; }; "host": { "alias": "host"; "required": false; "isSignal": true; }; "theme": { "alias": "theme"; "required": false; "isSignal": true; }; "test": { "alias": "test"; "required": false; "isSignal": true; }; "webview": { "alias": "webview"; "required": false; "isSignal": true; }; }, { "challengeHidden": "challengeHidden"; "challengeVisible": "challengeVisible"; "success": "success"; "networkError": "networkError"; "tokenExpired": "tokenExpired"; "javascriptError": "javascriptError"; }, never, never, true, never>;
50
+ }
51
+ export declare class InvisibleSmartCaptchaComponent extends SmartCaptchaComponent implements OnInit {
52
+ invisible: import("@angular/core").InputSignal<boolean>;
53
+ ngOnInit(): void;
54
+ static ɵfac: i0.ɵɵFactoryDeclaration<InvisibleSmartCaptchaComponent, never>;
55
+ static ɵcmp: i0.ɵɵComponentDeclaration<InvisibleSmartCaptchaComponent, "invisible-smart-captcha", never, { "invisible": { "alias": "invisible"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
56
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@ngx-rock/yandex-smart-captcha",
3
+ "version": "17.0.0",
4
+ "description": "Yandex smart captcha",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git@github.com:ngx-rock/yandex-smart-captcha.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/ngx-rock/yandex-smart-captcha/issues"
12
+ },
13
+ "homepage": "https://github.com/ngx-rock/yandex-smart-captcha#readme",
14
+ "keywords": [
15
+ "angular",
16
+ "ng",
17
+ "yandex smart captcha",
18
+ "captcha"
19
+ ],
20
+ "peerDependencies": {
21
+ "@angular/common": ">=17.3.0",
22
+ "@angular/core": ">=17.3.0",
23
+ "@angular/forms": ">=17.3.0"
24
+ },
25
+ "sideEffects": false,
26
+ "module": "fesm2022/ngx-rock-yandex-smart-captcha.mjs",
27
+ "typings": "index.d.ts",
28
+ "exports": {
29
+ "./package.json": {
30
+ "default": "./package.json"
31
+ },
32
+ ".": {
33
+ "types": "./index.d.ts",
34
+ "default": "./fesm2022/ngx-rock-yandex-smart-captcha.mjs"
35
+ }
36
+ },
37
+ "dependencies": {
38
+ "tslib": "^2.3.0"
39
+ }
40
+ }