@descope/web-components-ui 1.0.290 → 1.0.292

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.
Files changed (40) hide show
  1. package/dist/cjs/index.cjs.js +1336 -912
  2. package/dist/cjs/index.cjs.js.map +1 -1
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.esm.js +1565 -967
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/umd/1000.js +1 -1
  7. package/dist/umd/descope-grid-index-js.js +1 -1
  8. package/dist/umd/descope-new-password-descope-new-password-internal-index-js.js +1 -1
  9. package/dist/umd/descope-new-password-index-js.js +1 -1
  10. package/dist/umd/descope-policy-validation-index-js.js +1 -0
  11. package/dist/umd/index.js +1 -1
  12. package/dist/umd/mapping-fields-descope-mappings-field-descope-mapping-item-index-js.js +1 -1
  13. package/dist/umd/mapping-fields-descope-mappings-field-descope-mappings-field-internal-index-js.js +1 -1
  14. package/dist/umd/mapping-fields-descope-mappings-field-index-js.js +2 -2
  15. package/dist/umd/mapping-fields-descope-saml-group-mappings-descope-saml-group-mappings-internal-index-js.js +1 -0
  16. package/dist/umd/mapping-fields-descope-saml-group-mappings-index-js.js +1 -0
  17. package/package.json +1 -1
  18. package/src/components/descope-new-password/NewPasswordClass.js +30 -2
  19. package/src/components/descope-new-password/descope-new-password-internal/NewPasswordInternal.js +51 -3
  20. package/src/components/descope-new-password/index.js +1 -0
  21. package/src/components/descope-policy-validation/PolicyValidationClass.js +220 -0
  22. package/src/components/descope-policy-validation/helpers.js +2 -0
  23. package/src/components/descope-policy-validation/index.js +5 -0
  24. package/src/components/mapping-fields/descope-mappings-field/MappingsFieldClass.js +14 -1
  25. package/src/components/mapping-fields/descope-mappings-field/descope-mapping-item/MappingItem.js +1 -1
  26. package/src/components/mapping-fields/descope-mappings-field/descope-mappings-field-internal/MappingsFieldInternal.js +2 -2
  27. package/src/components/mapping-fields/descope-saml-group-mappings/SamlGroupMappingsClass.js +110 -0
  28. package/src/components/mapping-fields/descope-saml-group-mappings/descope-saml-group-mappings-internal/SamlGroupMappingsInternal.js +136 -0
  29. package/src/components/mapping-fields/descope-saml-group-mappings/descope-saml-group-mappings-internal/index.js +3 -0
  30. package/src/components/mapping-fields/descope-saml-group-mappings/index.js +10 -0
  31. package/src/index.cjs.js +2 -0
  32. package/src/index.d.ts +2 -0
  33. package/src/index.js +2 -0
  34. package/src/mixins/proxyInputMixin.js +7 -0
  35. package/src/theme/components/index.js +4 -0
  36. package/src/theme/components/inputWrapper.js +3 -1
  37. package/src/theme/components/mappingsField.js +3 -1
  38. package/src/theme/components/newPassword.js +5 -0
  39. package/src/theme/components/policyValidation.js +29 -0
  40. package/src/theme/components/samlGroupMappings.js +13 -0
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunkDescopeUI=self.webpackChunkDescopeUI||[]).push([[9476,9656],{6867:(e,t,i)=>{i.d(t,{Z:()=>p,f:()=>a});var n=i(3878),s=i(4567);const a=(0,s.iY)("saml-group-mappings-internal"),l=(0,n.P)({componentName:a,baseSelector:""}),p=class extends l{static get observedAttributes(){return["invalid"].concat(l.observedAttributes||[])}constructor(){super(),this.innerHTML='\n <descope-text-field variant="body2" bordered="true"></descope-text-field>\n <descope-mappings-field></descope-mappings-field>\n ',this.groupInputElement=this.querySelector("descope-text-field"),this.mappingsElement=this.querySelector("descope-mappings-field")}resetInvalidIndication(){this.removeAttribute("invalid")}handleMappingsInvalidChange(e){e.includes("invalid")&&(this.mappingsElement.hasAttribute("invalid")||this.resetInvalidIndication())}initFocusHandler(){this.addEventListener("focus",(e=>{e.isTrusted&&(this.mappingsElement.checkValidity()?this.groupInputElement:this.mappingsElement).focus()}))}init(){this.initFocusHandler(),super.init?.(),(0,s.oP)(this,this.groupInputElement,{mapAttrs:{"label-group":"label"},includeAttrs:["size","label-group","readonly","disabled"]}),(0,s.oP)(this,this.mappingsElement,{includeAttrs:["size","full-width","label-value","label-attr","button-label","separator","options","readonly","disabled","data-errormessage-pattern-mismatch"]}),(0,s.FX)(this.mappingsElement,this.handleMappingsInvalidChange.bind(this),{includeAttrs:["invalid"]})}get value(){return{group:this.groupInputElement.value,mappings:this.mappingsElement.value}}set value(e){e?.group&&"string"==typeof e.group&&(this.groupInputElement.value=e.group),Array.isArray(e?.mappings)&&(this.mappingsElement.value=e.mappings)}getValidity(){return this.groupInputElement.checkValidity()?this.mappingsElement.checkValidity()?{}:this.mappingsElement.validity:this.groupInputElement.validity}#e(e){if(e){if(!this.groupInputElement.checkValidity())return void this.groupInputElement.setAttribute("invalid","true");this.mappingsElement.checkValidity()||this.mappingsElement.setAttribute("invalid","true")}}attributeChangedCallback(e,t,i){super.attributeChangedCallback?.(e,t,i),"invalid"===e&&this.#e("true"===i)}}},4115:(e,t,i)=>{i.r(t);var n=i(6867);customElements.define(n.f,n.Z)},3277:(e,t,i)=>{i.r(t),i.d(t,{SamlGroupMappingsClass:()=>d}),i(9381);var n=i(1e3),s=i(2061),a=i(4567),l=i(6867);const p=(0,a.iY)("saml-group-mappings"),{host:r,groupInput:o}={host:{selector:()=>":host"},groupInput:{selector:"descope-text-field"}},d=(0,s.qC)((0,n.yk)({mappings:{hostWidth:{...r,property:"width"},hostDirection:{...r,property:"direction"},groupNameInputMarginBottom:{...o,property:"margin-bottom"}}}),n.e4,(0,n.dj)({proxyProps:["value","selectionStart"],inputEvent:"input",triggerValidationEvents:["mapping-item-added","mapping-item-removed"],proxyParentValidation:!0}),n.Ae,(e=>class extends e{init(){super.init?.();const e=document.createElement("template");e.innerHTML=`\n <${l.f}\n tabindex="-1"\n ></${l.f}>\n `,this.baseElement.appendChild(e.content.cloneNode(!0)),this.inputElement=this.shadowRoot.querySelector(l.f),(0,a.oP)(this,this.inputElement,{includeAttrs:["size","full-width","label-group","label-value","label-attr","button-label","separator","options","readonly","disabled"]}),(0,a.tg)(this,this.inputElement,{includeAttrs:["invalid"]})}}))((0,n.DM)({slots:[],wrappedEleName:"vaadin-custom-field",style:()=>"\n :host {\n display: inline-flex;\n max-width: 100%;\n direction: ltr;\n }\n\n vaadin-custom-field {\n line-height: unset;\n width: 100%;\n }\n\n descope-text-field {\n width: auto;\n }\n\n descope-mappings-field {\n display: block;\n }\n ",excludeAttrsSync:["tabindex","label-group","label-value","label-attr","button-label","separator","options","error-message"],componentName:p}));i(9357),i(5894),i(4115),customElements.define(p,d)}}]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descope/web-components-ui",
3
- "version": "1.0.290",
3
+ "version": "1.0.292",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -4,9 +4,12 @@ import { createStyleMixin, proxyInputMixin, draggableMixin, createProxy } from '
4
4
  import { componentName as descopeInternalComponentName } from './descope-new-password-internal/componentName';
5
5
  import { PasswordClass } from '../descope-password/PasswordClass';
6
6
  import { useHostExternalPadding } from '../../helpers/themeHelpers/resetHelpers';
7
+ import { PolicyValidationClass } from '../descope-policy-validation';
7
8
 
8
9
  export const componentName = getComponentName('new-password');
9
10
 
11
+ const policyPreviewVars = PolicyValidationClass.cssVarList;
12
+
10
13
  const customMixin = (superclass) =>
11
14
  class NewPasswordMixinClass extends superclass {
12
15
  init() {
@@ -40,18 +43,32 @@ const customMixin = (superclass) =>
40
43
  'invalid',
41
44
  'readonly',
42
45
  'draggable',
46
+ 'has-validation',
47
+ 'policy-label',
48
+ 'active-policies',
49
+ 'available-policies',
50
+ 'data-password-policy-value-minlength',
43
51
  ],
44
52
  });
45
53
  }
46
54
  };
47
55
 
48
- const { host, label, internalInputsWrapper, errorMessage, helperText, passwordInput } = {
56
+ const {
57
+ host,
58
+ label,
59
+ internalInputsWrapper,
60
+ errorMessage,
61
+ helperText,
62
+ passwordInput,
63
+ policyPreview,
64
+ } = {
49
65
  host: { selector: () => ':host' },
50
66
  label: { selector: '::part(label)' },
51
67
  internalInputsWrapper: { selector: 'descope-new-password-internal .wrapper' },
52
68
  helperText: { selector: '::part(helper-text)' },
53
69
  errorMessage: { selector: '::part(error-message)' },
54
70
  passwordInput: { selector: 'descope-password' },
71
+ policyPreview: { selector: 'descope-policy-validation' },
55
72
  };
56
73
 
57
74
  export const NewPasswordClass = compose(
@@ -75,6 +92,11 @@ export const NewPasswordClass = compose(
75
92
  ],
76
93
  inputsRequiredIndicator: { ...host, property: 'content' },
77
94
  spaceBetweenInputs: { ...internalInputsWrapper, property: 'gap' },
95
+ policyPreviewBackgroundColor: {
96
+ ...policyPreview,
97
+ property: policyPreviewVars.backgroundColor,
98
+ },
99
+ policyPreviewPadding: { ...policyPreview, property: policyPreviewVars.padding },
78
100
  },
79
101
  }),
80
102
  draggableMixin,
@@ -113,7 +135,6 @@ export const NewPasswordClass = compose(
113
135
  -webkit-mask-image: none;
114
136
  min-height: 0;
115
137
  width: 100%;
116
- height: 100%;
117
138
  padding: 0;
118
139
  }
119
140
  descope-new-password-internal > .wrapper {
@@ -129,6 +150,13 @@ export const NewPasswordClass = compose(
129
150
  descope-new-password-internal vaadin-password-field::before {
130
151
  height: initial;
131
152
  }
153
+ descope-policy-validation {
154
+ margin-top: 8px;
155
+ display: flex;
156
+ }
157
+ descope-policy-validation.hidden {
158
+ display: none;
159
+ }
132
160
  `,
133
161
  excludeAttrsSync: ['tabindex'],
134
162
  componentName,
@@ -1,5 +1,5 @@
1
1
  import { createBaseInputClass } from '../../../baseClasses/createBaseInputClass';
2
- import { observeAttributes } from '../../../helpers/componentHelpers';
2
+ import { forwardAttrs, observeAttributes } from '../../../helpers/componentHelpers';
3
3
  import { NewPasswordClass } from '../NewPasswordClass';
4
4
  import { componentName } from './componentName';
5
5
 
@@ -10,6 +10,7 @@ const removeAttrPrefix = (attr, prefix) => attr.replace(prefix, '');
10
10
 
11
11
  const passwordInputAttrs = ['password-label', 'password-placeholder'];
12
12
  const confirmInputAttrs = ['confirm-label', 'confirm-placeholder'];
13
+ const policyPanelAttrs = ['has-validation'];
13
14
  const commonAttrs = [
14
15
  'disabled',
15
16
  'bordered',
@@ -22,7 +23,12 @@ const commonAttrs = [
22
23
  'autocomplete',
23
24
  ];
24
25
 
25
- const inputRelatedAttrs = [].concat(commonAttrs, passwordInputAttrs, confirmInputAttrs);
26
+ const inputRelatedAttrs = [].concat(
27
+ commonAttrs,
28
+ passwordInputAttrs,
29
+ confirmInputAttrs,
30
+ policyPanelAttrs
31
+ );
26
32
 
27
33
  const BaseInputClass = createBaseInputClass({ componentName, baseSelector: 'div' });
28
34
 
@@ -54,7 +60,15 @@ class NewPasswordInternal extends BaseInputClass {
54
60
  return this.getAttribute('has-confirm') === 'true';
55
61
  }
56
62
 
63
+ get hasValidation() {
64
+ return this.getAttribute('has-validation') === 'true';
65
+ }
66
+
57
67
  getValidity() {
68
+ if (!this.policyPanel.isValid) {
69
+ return { patternMismatch: true };
70
+ }
71
+
58
72
  if (this.isRequired && !this.value) {
59
73
  return { valueMissing: true };
60
74
  }
@@ -85,7 +99,12 @@ class NewPasswordInternal extends BaseInputClass {
85
99
  }
86
100
 
87
101
  renderInputs(shouldRenderConfirm) {
88
- let template = `<descope-password data-id="password"></descope-password>`;
102
+ let template = `
103
+ <div>
104
+ <descope-password data-id="password"></descope-password>
105
+ <descope-policy-validation></descope-policy-validation>
106
+ </div>
107
+ `;
89
108
 
90
109
  if (shouldRenderConfirm) {
91
110
  template += `<descope-password data-id="confirm"></descope-password>`;
@@ -95,6 +114,7 @@ class NewPasswordInternal extends BaseInputClass {
95
114
 
96
115
  this.passwordInput = this.querySelector('[data-id="password"]');
97
116
  this.confirmInput = this.querySelector('[data-id="confirm"]');
117
+ this.policyPanel = this.querySelector('descope-policy-validation');
98
118
 
99
119
  this.inputs = [this.passwordInput, this.confirmInput];
100
120
 
@@ -105,6 +125,23 @@ class NewPasswordInternal extends BaseInputClass {
105
125
  [...passwordInputAttrs, ...confirmInputAttrs, ...commonAttrs].forEach((attr) => {
106
126
  this.attributeChangedCallback(attr, null, this.getAttribute(attr));
107
127
  });
128
+
129
+ this.passwordInput.addEventListener('input', (e) => {
130
+ this.policyPanel.setAttribute('value', e.target.value);
131
+ });
132
+
133
+ forwardAttrs(this, this.policyPanel, {
134
+ includeAttrs: [
135
+ 'policy-label',
136
+ 'available-policies',
137
+ 'active-policies',
138
+ 'data-password-policy-value-minlength',
139
+ ],
140
+ mapAttrs: {
141
+ 'policy-label': 'label',
142
+ 'available-policies': 'data',
143
+ },
144
+ });
108
145
  }
109
146
 
110
147
  // the inputs are not required but we still want it to have a required
@@ -164,6 +201,14 @@ class NewPasswordInternal extends BaseInputClass {
164
201
  value === null ? ele?.removeAttribute(name) : ele?.setAttribute(name, value);
165
202
  }
166
203
 
204
+ hidePolicy() {
205
+ this.policyPanel.classList.add('hidden');
206
+ }
207
+
208
+ showPolicy() {
209
+ this.policyPanel.classList.remove('hidden');
210
+ }
211
+
167
212
  attributeChangedCallback(attrName, oldValue, newValue) {
168
213
  super.attributeChangedCallback?.(attrName, oldValue, newValue);
169
214
 
@@ -185,6 +230,9 @@ class NewPasswordInternal extends BaseInputClass {
185
230
  newValue
186
231
  );
187
232
  }
233
+ if (attrName === 'has-validation') {
234
+ newValue === 'true' ? this.showPolicy() : this.hidePolicy();
235
+ }
188
236
  }
189
237
  }
190
238
  }
@@ -1,6 +1,7 @@
1
1
  import { componentName, NewPasswordClass } from './NewPasswordClass';
2
2
  import '../descope-text-field';
3
3
  import '../descope-password';
4
+ import '../descope-policy-validation';
4
5
  import './descope-new-password-internal';
5
6
 
6
7
  customElements.define(componentName, NewPasswordClass);
@@ -0,0 +1,220 @@
1
+ // eslint-disable-next-line max-classes-per-file
2
+ import { createStyleMixin, draggableMixin, componentNameValidationMixin } from '../../mixins';
3
+ import { createBaseClass } from '../../baseClasses/createBaseClass';
4
+ import { compose } from '../../helpers';
5
+ import { getComponentName } from '../../helpers/componentHelpers';
6
+ import { interpolateString } from './helpers';
7
+
8
+ export const componentName = getComponentName('policy-validation');
9
+
10
+ const overrideAttrs = ['data-password-policy-value-minlength'];
11
+ const dataAttrs = ['data', 'active-policies', 'overrides', ...overrideAttrs];
12
+ const policyAttrs = ['label', 'value', ...dataAttrs];
13
+
14
+ class RawPolicyValidation extends createBaseClass({ componentName, baseSelector: ':host > div' }) {
15
+ #availablePolicies;
16
+
17
+ #activePolicies = [];
18
+
19
+ #overrides;
20
+
21
+ static get observedAttributes() {
22
+ return policyAttrs;
23
+ }
24
+
25
+ constructor() {
26
+ super();
27
+
28
+ this.attachShadow({ mode: 'open' }).innerHTML = `
29
+ <div>
30
+ <div class="label"></div>
31
+ <ul></ul>
32
+ </div>
33
+ <style>
34
+ :host > div {
35
+ width: 100%;
36
+ display: flex;
37
+ flex-direction: column;
38
+ box-sizing: border-box;
39
+ }
40
+ .label {
41
+ max-width: 100%;
42
+ text-wrap: wrap;
43
+ overflow-wrap: break-word;
44
+ }
45
+ .hide-label .label {
46
+ display: none;
47
+ }
48
+ ul {
49
+ display: flex;
50
+ flex-direction: column;
51
+ padding: 0;
52
+ margin: 0;
53
+ }
54
+ ul, li {
55
+ margin: 0;
56
+ padding: 0;
57
+ list-style: none;
58
+ }
59
+ li::before {
60
+ display: inline-block;
61
+ width: 1em;
62
+ text-align: center;
63
+ }
64
+ </style>
65
+ `;
66
+
67
+ this.panel = this.shadowRoot.querySelector(':host > div');
68
+ this.label = this.shadowRoot.querySelector('.label');
69
+ this.list = this.shadowRoot.querySelector('ul');
70
+ }
71
+
72
+ attributeChangedCallback(attrName, oldValue, newValue) {
73
+ super.attributeChangedCallback?.(attrName, oldValue, newValue);
74
+ if (oldValue !== newValue) {
75
+ if (attrName === 'label') {
76
+ this.updateLabel(newValue);
77
+ }
78
+
79
+ // we're don't know the order in which the attributes are forwarded, so we're trying to render every time
80
+ // once `data` and `active-policies` are populated, the render will be executed.
81
+ // once the `overrides` object is updated, we want to re-render the panel.
82
+ if (dataAttrs.includes(attrName)) {
83
+ if (attrName === 'data') {
84
+ try {
85
+ this.availablePolicies = JSON.parse(newValue);
86
+ } catch {
87
+ // eslint-disable-next-line no-console
88
+ console.error('Failed to set available policies');
89
+ }
90
+ }
91
+ if (attrName === 'active-policies') {
92
+ this.#activePolicies = (newValue || '').split(',');
93
+ }
94
+
95
+ if (attrName === 'data-password-policy-value-minlength') {
96
+ const ln = Number(newValue);
97
+ if (!Number.isNaN(ln) && ln > 0) {
98
+ this.#overrides = { ...this.#overrides, minlength: { value: `${ln}` } };
99
+ }
100
+ }
101
+ }
102
+
103
+ this.renderItems(this.#availablePolicies, this.#activePolicies, this.#overrides);
104
+ }
105
+ }
106
+
107
+ get availablePolicies() {
108
+ return this.#availablePolicies || [];
109
+ }
110
+
111
+ set availablePolicies(val) {
112
+ this.#availablePolicies = val;
113
+ }
114
+
115
+ get value() {
116
+ return this.getAttribute('value') || '';
117
+ }
118
+
119
+ validate() {
120
+ let policies = this.#availablePolicies;
121
+
122
+ if (this.#overrides) {
123
+ policies = this.#availablePolicies.map((policy) =>
124
+ this.#overrides[policy.id] ? { ...policy, data: this.#overrides[policy.id] } : policy
125
+ );
126
+ }
127
+
128
+ return this.#activePolicies.reduce((results, id) => {
129
+ const policy = policies.find((p) => p.id === id);
130
+
131
+ if (!policy) {
132
+ return results;
133
+ }
134
+
135
+ const { pattern, message, data } = policy;
136
+
137
+ if (!pattern || !message) {
138
+ return results;
139
+ }
140
+
141
+ const exp = new RegExp(interpolateString(pattern, data));
142
+
143
+ const validationResult = {
144
+ valid: exp.test(this.value),
145
+ message: interpolateString(message, data),
146
+ id,
147
+ };
148
+
149
+ results.push(validationResult);
150
+
151
+ return results;
152
+ }, []);
153
+ }
154
+
155
+ get isValid() {
156
+ return !this.validate().some(({ valid }) => valid === false);
157
+ }
158
+
159
+ getValidationItemTemplate({ valid, message }) {
160
+ const status = !this.value ? 'none' : valid;
161
+ return `
162
+ <li class="item" data-valid="${status}">
163
+ <span class="message">${message}</span>
164
+ </li>
165
+ `;
166
+ }
167
+
168
+ renderItems(availablePolicies, activePolicies) {
169
+ if (!availablePolicies || !activePolicies.length) {
170
+ return;
171
+ }
172
+
173
+ this.list.innerHTML = this.validate().map(this.getValidationItemTemplate.bind(this)).join('');
174
+ }
175
+
176
+ updateLabel(val) {
177
+ if (!val) {
178
+ this.classList.add('hide-label');
179
+ this.label.innerHTML = '';
180
+ } else {
181
+ this.label.innerHTML = val;
182
+ this.classList.remove('hide-label');
183
+ }
184
+ }
185
+ }
186
+
187
+ const { host, item, symbolDefault, symbolSuccess, symbolError } = {
188
+ host: { selector: () => ':host > div' },
189
+ item: { selector: () => '.item' },
190
+ symbolDefault: { selector: () => '.item[data-valid="none"]::before' },
191
+ symbolSuccess: { selector: () => '.item[data-valid="true"]::before' },
192
+ symbolError: { selector: () => '.item[data-valid="false"]::before' },
193
+ };
194
+
195
+ export const PolicyValidationClass = compose(
196
+ createStyleMixin({ componentNameOverride: getComponentName('input-wrapper') }),
197
+ createStyleMixin({
198
+ mappings: {
199
+ hostDirection: { selector: () => ':host', property: 'direction' },
200
+ fontSize: {},
201
+ fontFamily: {},
202
+ padding: {},
203
+ borderWidth: { ...host, property: 'border-width' },
204
+ borderStyle: { ...host, property: 'border-style' },
205
+ borderColor: { ...host, property: 'border-color' },
206
+ borderRadius: { ...host, property: 'border-radius' },
207
+ backgroundColor: { ...host, property: 'background-color' },
208
+ textColor: { property: 'color' },
209
+ labelMargin: { ...host, property: 'gap' },
210
+ itemsSpacing: { ...item, property: 'line-height' },
211
+ itemSymbolSuccessColor: { ...symbolSuccess, property: 'color' },
212
+ itemSymbolErrorColor: { ...symbolError, property: 'color' },
213
+ itemSymbolDefault: { ...symbolDefault, property: 'content' },
214
+ itemSymbolSuccess: { ...symbolSuccess, property: 'content' },
215
+ itemSymbolError: { ...symbolError, property: 'content' },
216
+ },
217
+ }),
218
+ draggableMixin,
219
+ componentNameValidationMixin
220
+ )(RawPolicyValidation);
@@ -0,0 +1,2 @@
1
+ export const interpolateString = (template, values) =>
2
+ template.replace(/{{(\w+)+}}/g, (match, key) => values?.[key] || match);
@@ -0,0 +1,5 @@
1
+ import { componentName, PolicyValidationClass } from './PolicyValidationClass';
2
+
3
+ customElements.define(componentName, PolicyValidationClass);
4
+
5
+ export { PolicyValidationClass };
@@ -7,7 +7,7 @@ import {
7
7
  } from '../../../mixins';
8
8
  import { TextClass } from '../../descope-text/TextClass';
9
9
  import { compose } from '../../../helpers';
10
- import { forwardAttrs, getComponentName } from '../../../helpers/componentHelpers';
10
+ import { forwardAttrs, getComponentName, syncAttrs } from '../../../helpers/componentHelpers';
11
11
  import { componentName as descopeInternalComponentName } from './descope-mappings-field-internal/MappingsFieldInternal';
12
12
 
13
13
  export const componentName = getComponentName('mappings-field');
@@ -64,6 +64,10 @@ const customMixin = (superclass) =>
64
64
  ],
65
65
  });
66
66
 
67
+ // This is required since when we remove the invalid attribute from the internal mappings field,
68
+ // we want to reflect the change in the parent component
69
+ syncAttrs(this, this.inputElement, { includeAttrs: ['invalid'] });
70
+
67
71
  this.setDefaultValues();
68
72
  }
69
73
  };
@@ -74,6 +78,7 @@ const {
74
78
  errorMessage,
75
79
  mappingItem,
76
80
  labels,
81
+ labelsText,
77
82
  valueLabel,
78
83
  attrLabel,
79
84
  separator,
@@ -84,6 +89,9 @@ const {
84
89
  errorMessage: { selector: '::part(error-message)' },
85
90
  mappingItem: { selector: 'descope-mapping-item::part(wrapper)' },
86
91
  labels: { selector: 'descope-mappings-field-internal [part="labels"] descope-text' },
92
+ labelsText: {
93
+ selector: 'descope-mappings-field-internal [part="labels"] descope-text::part(text-wrapper)',
94
+ },
87
95
  valueLabel: { selector: 'descope-mappings-field-internal [part="labels"] [part="value-label"]' },
88
96
  attrLabel: { selector: 'descope-mappings-field-internal [part="labels"] [part="attr-label"]' },
89
97
  separator: { selector: 'descope-mapping-item::part(separator)' },
@@ -99,6 +107,11 @@ export const MappingsFieldClass = compose(
99
107
  fontSize: [{}, host, { ...separator, property: 'margin-top' }],
100
108
  fontFamily: [helperText, errorMessage, labels],
101
109
  separatorFontSize: { ...separator, property: 'font-size' },
110
+ labelsFontSize: { ...labelsText, property: 'font-size' },
111
+ labelsLineHeight: [
112
+ { ...labelsText, property: 'line-height' },
113
+ { ...labels, property: 'line-height' },
114
+ ],
102
115
  labelTextColor: { ...labels, property: TextClass.cssVarList.textColor },
103
116
  itemMarginBottom: { ...mappingItem, property: 'margin-bottom' },
104
117
  valueLabelMinWidth: { ...valueLabel, property: 'min-width' },
@@ -92,7 +92,7 @@ class MappingItem extends BaseInputClass {
92
92
 
93
93
  initRemoveButton() {
94
94
  this.removeButton.addEventListener('click', () =>
95
- this.dispatchEvent(new CustomEvent('mapping-item-removed'))
95
+ this.dispatchEvent(new CustomEvent('mapping-item-removed', { bubbles: true, composed: true }))
96
96
  );
97
97
  }
98
98
 
@@ -66,7 +66,7 @@ class MappingsFieldInternal extends BaseInputClass {
66
66
  // before the new item is added and thus returns a wrong result
67
67
  setTimeout(() => {
68
68
  this.setCustomValidity('');
69
- newMappingItem.addEventListener('mapping-item-removed', (e) => {
69
+ newMappingItem.addEventListener('mapping-item-removed', () => {
70
70
  // If the removed item was the one that was invalid, we need to reset the invalid indication for the internal
71
71
  if (newMappingItem === this.#errorItem) {
72
72
  this.resetInvalidIndication();
@@ -74,8 +74,8 @@ class MappingsFieldInternal extends BaseInputClass {
74
74
  }
75
75
  newMappingItem.remove();
76
76
  this.setCustomValidity('');
77
- e.stopPropagation();
78
77
  });
78
+ this.dispatchEvent(new CustomEvent('mapping-item-added', { bubbles: true, composed: true }));
79
79
  if (focusNewItem) {
80
80
  newMappingItem.focus();
81
81
  }
@@ -0,0 +1,110 @@
1
+ import {
2
+ createStyleMixin,
3
+ draggableMixin,
4
+ createProxy,
5
+ proxyInputMixin,
6
+ componentNameValidationMixin,
7
+ } from '../../../mixins';
8
+ import { compose } from '../../../helpers';
9
+ import { forwardAttrs, getComponentName, syncAttrs } from '../../../helpers/componentHelpers';
10
+ import { componentName as descopeInternalComponentName } from './descope-saml-group-mappings-internal/SamlGroupMappingsInternal';
11
+
12
+ export const componentName = getComponentName('saml-group-mappings');
13
+
14
+ const customMixin = (superclass) =>
15
+ class SamlGroupMappingsMixinClass extends superclass {
16
+ init() {
17
+ super.init?.();
18
+
19
+ const template = document.createElement('template');
20
+
21
+ template.innerHTML = `
22
+ <${descopeInternalComponentName}
23
+ tabindex="-1"
24
+ ></${descopeInternalComponentName}>
25
+ `;
26
+
27
+ this.baseElement.appendChild(template.content.cloneNode(true));
28
+
29
+ this.inputElement = this.shadowRoot.querySelector(descopeInternalComponentName);
30
+
31
+ forwardAttrs(this, this.inputElement, {
32
+ includeAttrs: [
33
+ 'size',
34
+ 'full-width',
35
+ 'label-group',
36
+ 'label-value',
37
+ 'label-attr',
38
+ 'button-label',
39
+ 'separator',
40
+ 'options',
41
+ 'readonly',
42
+ 'disabled',
43
+ ],
44
+ });
45
+
46
+ syncAttrs(this, this.inputElement, { includeAttrs: ['invalid'] });
47
+ }
48
+ };
49
+
50
+ const { host, groupInput } = {
51
+ host: { selector: () => ':host' },
52
+ groupInput: { selector: 'descope-text-field' },
53
+ };
54
+
55
+ export const SamlGroupMappingsClass = compose(
56
+ createStyleMixin({
57
+ mappings: {
58
+ hostWidth: { ...host, property: 'width' },
59
+ hostDirection: { ...host, property: 'direction' },
60
+ groupNameInputMarginBottom: { ...groupInput, property: 'margin-bottom' },
61
+ },
62
+ }),
63
+ draggableMixin,
64
+ proxyInputMixin({
65
+ proxyProps: ['value', 'selectionStart'],
66
+ inputEvent: 'input',
67
+ triggerValidationEvents: ['mapping-item-added', 'mapping-item-removed'],
68
+ proxyParentValidation: true,
69
+ }),
70
+ componentNameValidationMixin,
71
+ customMixin
72
+ )(
73
+ createProxy({
74
+ slots: [],
75
+ wrappedEleName: 'vaadin-custom-field',
76
+ style: () => `
77
+ :host {
78
+ display: inline-flex;
79
+ max-width: 100%;
80
+ direction: ltr;
81
+ }
82
+
83
+ vaadin-custom-field {
84
+ line-height: unset;
85
+ width: 100%;
86
+ }
87
+
88
+ descope-text-field {
89
+ width: auto;
90
+ }
91
+
92
+ descope-mappings-field {
93
+ display: block;
94
+ }
95
+ `,
96
+ excludeAttrsSync: [
97
+ 'tabindex',
98
+ 'label-group',
99
+ 'label-value',
100
+ 'label-attr',
101
+ 'button-label',
102
+ 'separator',
103
+ 'options',
104
+ 'error-message',
105
+ ],
106
+ componentName,
107
+ })
108
+ );
109
+
110
+ export default SamlGroupMappingsClass;