@descope/web-components-ui 3.2.2 → 3.3.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.
@@ -6,7 +6,7 @@ import { getComponentName, observeChildren } from '../../helpers/componentHelper
6
6
 
7
7
  export const componentName = getComponentName('recaptcha');
8
8
 
9
- const observedAttributes = ['enabled', 'site-key', 'action', 'enterprise'];
9
+ const observedAttributes = ['enabled', 'site-key', 'action', 'enterprise', 'variant'];
10
10
 
11
11
  const BaseClass = createBaseClass({
12
12
  componentName,
@@ -23,6 +23,10 @@ class RawRecaptcha extends BaseClass {
23
23
  if (attrName === 'enabled') {
24
24
  this.#toggleRecaptcha(newValue === 'true');
25
25
  }
26
+
27
+ if (attrName === 'variant') {
28
+ this.updatePreview();
29
+ }
26
30
  }
27
31
  }
28
32
 
@@ -35,13 +39,37 @@ class RawRecaptcha extends BaseClass {
35
39
  this.toggleRecaptchaEles(enabled);
36
40
  }
37
41
 
42
+ displayRecaptcha() {
43
+ if (this.isWidget) {
44
+ this.displayWidget();
45
+ } else {
46
+ this.displayDeprecated();
47
+ }
48
+ }
49
+
50
+ displayWidget() {
51
+ this.mockRecaptchaEle.style.display = 'none';
52
+ this.recaptchaWidgetEle.style.display = '';
53
+ this.depercatedRecaptchaEle.style.display = 'none';
54
+ }
55
+
56
+ hideRecaptcha() {
57
+ this.recaptchaWidgetEle.style.display = 'none';
58
+ this.depercatedRecaptchaEle.style.display = 'none';
59
+ this.mockRecaptchaEle.style.display = '';
60
+ }
61
+
62
+ displayDeprecated() {
63
+ this.mockRecaptchaEle.style.display = 'none';
64
+ this.recaptchaWidgetEle.style.display = 'none';
65
+ this.depercatedRecaptchaEle.style.display = '';
66
+ }
67
+
38
68
  toggleRecaptchaEles(enabled) {
39
69
  if (enabled) {
40
- this.recaptchaEle.style.display = '';
41
- this.mockRecaptchaEle.style.display = 'none';
70
+ this.displayRecaptcha();
42
71
  } else {
43
- this.recaptchaEle.style.display = 'none';
44
- this.mockRecaptchaEle.style.display = '';
72
+ this.hideRecaptcha();
45
73
  }
46
74
  }
47
75
 
@@ -51,6 +79,8 @@ class RawRecaptcha extends BaseClass {
51
79
  this.attachShadow({ mode: 'open' }).innerHTML = `
52
80
  <div class="badge">
53
81
  <span id="recaptcha"></span>
82
+ <span id="recaptcha-widget"></span>
83
+ <input id="recaptcha-widget-input" type="hidden" name="recaptcha-widget" required />
54
84
  <img src="https://imgs.descope.com/connectors/templates/recaptcha/recaptcha-big.png" alt="recaptcha"/>
55
85
  </div>
56
86
  <slot></slot>
@@ -74,6 +104,13 @@ class RawRecaptcha extends BaseClass {
74
104
  width: 100%;
75
105
  height: 100%;
76
106
  }
107
+ :host #recaptcha-widget {
108
+ width: 100%;
109
+ height: 100%;
110
+ }
111
+ :host #recaptcha-widget-input {
112
+ display: none;
113
+ }
77
114
  :host img {
78
115
  width: 256px;
79
116
  }
@@ -87,7 +124,9 @@ class RawRecaptcha extends BaseClass {
87
124
  this
88
125
  );
89
126
 
90
- this.recaptchaEle = this.baseElement.querySelector('#recaptcha');
127
+ this.depercatedRecaptchaEle = this.baseElement.querySelector('#recaptcha');
128
+ this.recaptchaWidgetEle = this.baseElement.querySelector('#recaptcha-widget');
129
+ this.recaptchaWidgetInputEle = this.baseElement.querySelector('#recaptcha-widget-input');
91
130
  this.mockRecaptchaEle = this.baseElement.querySelector('img');
92
131
  this.badge = this.shadowRoot.querySelector('.badge');
93
132
  }
@@ -100,7 +139,8 @@ class RawRecaptcha extends BaseClass {
100
139
 
101
140
  updatePreview() {
102
141
  if (this.children.length) {
103
- this.recaptchaEle.style.display = 'none';
142
+ this.depercatedRecaptchaEle.style.display = 'none';
143
+ this.recaptchaWidgetEle.style.display = 'none';
104
144
  this.mockRecaptchaEle.style.display = 'none';
105
145
  this.badge.classList.add('hidden');
106
146
  } else {
@@ -109,6 +149,26 @@ class RawRecaptcha extends BaseClass {
109
149
  }
110
150
  }
111
151
 
152
+ getValidity() {
153
+ if (!this.isWidget) {
154
+ return {};
155
+ }
156
+
157
+ if (!this.recaptchaWidgetInputEle.value) {
158
+ return { valueMissing: true };
159
+ }
160
+
161
+ return {};
162
+ }
163
+
164
+ checkValidity() {
165
+ if (!this.isWidget) {
166
+ return true;
167
+ }
168
+
169
+ return !!this.recaptchaWidgetInputEle.value;
170
+ }
171
+
112
172
  get enterprise() {
113
173
  return this.getAttribute('enterprise') === 'true';
114
174
  }
@@ -125,6 +185,14 @@ class RawRecaptcha extends BaseClass {
125
185
  return this.getAttribute('enabled') === 'true';
126
186
  }
127
187
 
188
+ get variant() {
189
+ return this.getAttribute('variant') || 'text';
190
+ }
191
+
192
+ get isWidget() {
193
+ return this.variant === 'widget';
194
+ }
195
+
128
196
  get scriptURL() {
129
197
  const url = new URL('https://www.google.com/recaptcha/');
130
198
  url.pathname += `${this.enterprise ? 'enterprise' : 'api'}.js`;
@@ -135,6 +203,11 @@ class RawRecaptcha extends BaseClass {
135
203
 
136
204
  #toggleRecaptcha(enabled) {
137
205
  this.renderRecaptcha(enabled);
206
+ if (this.isWidget) {
207
+ // For the v2 checkbox flow, scripts are loaded/executed by the runtime (grecaptcha-v2).
208
+ // This legacy v3/invisible path must be fully skipped.
209
+ return;
210
+ }
138
211
  if (enabled) {
139
212
  this.#createOnLoadScript();
140
213
  if (!document.getElementById('recaptcha-script')) {
@@ -207,7 +280,7 @@ class RawRecaptcha extends BaseClass {
207
280
 
208
281
  #createOnLoadScript() {
209
282
  window.onRecaptchaLoadCallback = () => {
210
- const currentNode = this.recaptchaEle;
283
+ const currentNode = this.depercatedRecaptchaEle;
211
284
 
212
285
  // if there are child nodes, it means that the recaptcha was already rendered
213
286
  if (currentNode.hasChildNodes()) {