@refinitiv-ui/elements 7.8.0 → 7.9.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/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [7.9.0](https://github.com/Refinitiv/refinitiv-ui/compare/@refinitiv-ui/elements@7.8.0...@refinitiv-ui/elements@7.9.0) (2023-11-06)
7
+
8
+ ### Features
9
+
10
+ - **core, elements:** custom validation for form fields ([#996](https://github.com/Refinitiv/refinitiv-ui/issues/996)) ([b8655a2](https://github.com/Refinitiv/refinitiv-ui/commit/b8655a2d2ea42aa16767ba1bd8b5ce9c67912f36))
11
+
6
12
  # [7.8.0](https://github.com/Refinitiv/refinitiv-ui/compare/@refinitiv-ui/elements@7.7.0...@refinitiv-ui/elements@7.8.0) (2023-10-31)
7
13
 
8
14
  ### Bug Fixes
@@ -138,7 +138,9 @@ export declare class ColorDialog extends Dialog {
138
138
  */
139
139
  protected update(changedProperties: PropertyValues): void;
140
140
  /**
141
- * @inheritdoc
141
+ * Make sure that confirm/cancel events are fired appropriately
142
+ * All internal opened set events can be stoppable externally
143
+ * Use this instead of setting opened directly
142
144
  * Reset value model
143
145
  * @param opened True if opened
144
146
  * @returns {void}
@@ -211,7 +211,9 @@ let ColorDialog = class ColorDialog extends Dialog {
211
211
  super.update(changedProperties);
212
212
  }
213
213
  /**
214
- * @inheritdoc
214
+ * Make sure that confirm/cancel events are fired appropriately
215
+ * All internal opened set events can be stoppable externally
216
+ * Use this instead of setting opened directly
215
217
  * Reset value model
216
218
  * @param opened True if opened
217
219
  * @returns {void}
@@ -1,3 +1,4 @@
1
+ import escapeStringRegexp from 'escape-string-regexp';
1
2
  /**
2
3
  * Default filter used by combo box
3
4
  * @param el ComboBox instance to filter
@@ -13,8 +14,8 @@ export const defaultFilter = (el) => {
13
14
  // only created once per query
14
15
  const getRegularExpressionOfQuery = () => {
15
16
  if (el.query !== query || !queryRegExp) {
16
- query = el.query || '';
17
- queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
17
+ query = el.query ?? '';
18
+ queryRegExp = new RegExp(escapeStringRegexp(query), 'i');
18
19
  }
19
20
  return queryRegExp;
20
21
  };
@@ -11,6 +11,21 @@
11
11
  "type": "boolean",
12
12
  "default": "false"
13
13
  },
14
+ {
15
+ "name": "pattern",
16
+ "description": "Set regular expression for input validation",
17
+ "type": "string | null"
18
+ },
19
+ {
20
+ "name": "maxlength",
21
+ "description": "Set character max limit",
22
+ "type": "number | null"
23
+ },
24
+ {
25
+ "name": "minlength",
26
+ "description": "Set character min limit",
27
+ "type": "number | null"
28
+ },
14
29
  {
15
30
  "name": "disabled",
16
31
  "description": "Set disabled state",
@@ -68,16 +83,6 @@
68
83
  "name": "icon-has-action",
69
84
  "description": "Specify when icon need to be clickable",
70
85
  "type": "boolean"
71
- },
72
- {
73
- "name": "maxlength",
74
- "description": "Set character max limit",
75
- "type": "number"
76
- },
77
- {
78
- "name": "minlength",
79
- "description": "Set character min limit",
80
- "type": "number"
81
86
  }
82
87
  ],
83
88
  "properties": [
@@ -88,6 +93,24 @@
88
93
  "type": "boolean",
89
94
  "default": "false"
90
95
  },
96
+ {
97
+ "name": "pattern",
98
+ "attribute": "pattern",
99
+ "description": "Set regular expression for input validation",
100
+ "type": "string | null"
101
+ },
102
+ {
103
+ "name": "maxLength",
104
+ "attribute": "maxlength",
105
+ "description": "Set character max limit",
106
+ "type": "number | null"
107
+ },
108
+ {
109
+ "name": "minLength",
110
+ "attribute": "minlength",
111
+ "description": "Set character min limit",
112
+ "type": "number | null"
113
+ },
91
114
  {
92
115
  "name": "disabled",
93
116
  "attribute": "disabled",
@@ -115,22 +138,6 @@
115
138
  "type": "boolean",
116
139
  "default": "false"
117
140
  },
118
- {
119
- "name": "maxLength",
120
- "description": "Set character max limit",
121
- "type": "number | null"
122
- },
123
- {
124
- "name": "minLength",
125
- "description": "Set character min limit",
126
- "type": "number | null"
127
- },
128
- {
129
- "name": "pattern",
130
- "description": "Set regular expression for input validation",
131
- "type": "string",
132
- "default": "\"\""
133
- },
134
141
  {
135
142
  "name": "placeholder",
136
143
  "attribute": "placeholder",
@@ -7,8 +7,6 @@ A form control element for email.
7
7
  | Attribute | Type | Description |
8
8
  |-------------------|-----------|----------------------------------------|
9
9
  | `icon-has-action` | `boolean` | Specify when icon need to be clickable |
10
- | `maxlength` | `number` | Set character max limit |
11
- | `minlength` | `number` | Set character min limit |
12
10
 
13
11
  ## Properties
14
12
 
@@ -18,10 +16,10 @@ A form control element for email.
18
16
  | `error` | `error` | `boolean` | false | Set error state |
19
17
  | `icon` | `icon` | `string \| null` | null | Specify icon to display in input. Value can be icon name |
20
18
  | `iconHasAction` | `icon-has-action` | `boolean` | false | Specify when icon need to be clickable |
21
- | `maxLength` | | `number \| null` | null | Set character max limit |
22
- | `minLength` | | `number \| null` | null | Set character min limit |
19
+ | `maxLength` | `maxlength` | `number \| null` | null | Set character max limit |
20
+ | `minLength` | `minlength` | `number \| null` | null | Set character min limit |
23
21
  | `multiple` | `multiple` | `boolean` | false | Set to multiple mode, allows multiple emails in a single input |
24
- | `pattern` | | `string` | "" | Set regular expression for input validation |
22
+ | `pattern` | `pattern` | `string \| null` | null | Set regular expression for input validation |
25
23
  | `placeholder` | `placeholder` | `string` | "" | Set placeholder text |
26
24
  | `readonly` | `readonly` | `boolean` | false | Set readonly state |
27
25
  | `transparent` | `transparent` | `boolean` | false | Disables all other states and border/background styles. |
@@ -21,14 +21,6 @@ import { TextField } from '../text-field/index.js';
21
21
  * @attr {boolean} icon-has-action - Specify when icon need to be clickable
22
22
  * @prop {boolean} [iconHasAction=false] - Specify when icon need to be clickable
23
23
  *
24
- * @attr {number} maxlength - Set character max limit
25
- * @prop {number | null} [maxLength=null] - Set character max limit
26
- *
27
- * @attr {number} minlength - Set character min limit
28
- * @prop {number | null} [minLength=null] - Set character min limit
29
- *
30
- * @prop {string} [pattern=""] - Set regular expression for input validation
31
- *
32
24
  * @attr {string} placeholder - Set placeholder text
33
25
  * @prop {string} [placeholder=""] - Set placeholder text
34
26
  *
@@ -49,6 +41,18 @@ export declare class EmailField extends TextField {
49
41
  * Set to multiple mode, allows multiple emails in a single input
50
42
  */
51
43
  multiple: boolean;
44
+ /**
45
+ * Set regular expression for input validation
46
+ */
47
+ pattern: string | null;
48
+ /**
49
+ * Set character max limit
50
+ */
51
+ maxLength: number | null;
52
+ /**
53
+ * Set character min limit
54
+ */
55
+ minLength: number | null;
52
56
  /**
53
57
  * Returns `true` if the element input is valid; otherwise, returns `false`.
54
58
  * @returns element input validity
@@ -59,6 +63,11 @@ export declare class EmailField extends TextField {
59
63
  * @returns `true` if the element input is valid; otherwise, returns `false`.
60
64
  */
61
65
  reportValidity(): boolean;
66
+ /**
67
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
68
+ * @returns true if there is at least one validation constraint
69
+ */
70
+ protected shouldValidate(): boolean;
62
71
  /**
63
72
  * Decorate `<input>` element with common properties extended from text-field:
64
73
  * type="email" - always `email`
@@ -22,14 +22,6 @@ import { TextField } from '../text-field/index.js';
22
22
  * @attr {boolean} icon-has-action - Specify when icon need to be clickable
23
23
  * @prop {boolean} [iconHasAction=false] - Specify when icon need to be clickable
24
24
  *
25
- * @attr {number} maxlength - Set character max limit
26
- * @prop {number | null} [maxLength=null] - Set character max limit
27
- *
28
- * @attr {number} minlength - Set character min limit
29
- * @prop {number | null} [minLength=null] - Set character min limit
30
- *
31
- * @prop {string} [pattern=""] - Set regular expression for input validation
32
- *
33
25
  * @attr {string} placeholder - Set placeholder text
34
26
  * @prop {string} [placeholder=""] - Set placeholder text
35
27
  *
@@ -52,6 +44,20 @@ let EmailField = class EmailField extends TextField {
52
44
  * Set to multiple mode, allows multiple emails in a single input
53
45
  */
54
46
  this.multiple = false;
47
+ /**
48
+ * Set regular expression for input validation
49
+ */
50
+ this.pattern = null;
51
+ /**
52
+ * Set character max limit
53
+ */
54
+ // override to merely fix missing attribute from component's doc
55
+ this.maxLength = null;
56
+ /**
57
+ * Set character min limit
58
+ */
59
+ // override to merely fix missing attribute from component's doc
60
+ this.minLength = null;
55
61
  }
56
62
  /**
57
63
  * Returns `true` if the element input is valid; otherwise, returns `false`.
@@ -67,6 +73,16 @@ let EmailField = class EmailField extends TextField {
67
73
  reportValidity() {
68
74
  return super.reportValidity();
69
75
  }
76
+ /**
77
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
78
+ * @returns true if there is at least one validation constraint
79
+ */
80
+ shouldValidate() {
81
+ const hasMaxLength = this.maxLength !== null;
82
+ const hasMinLength = this.minLength !== null;
83
+ const hasPattern = this.pattern !== '';
84
+ return hasMaxLength || hasMinLength || hasPattern;
85
+ }
70
86
  /**
71
87
  * Decorate `<input>` element with common properties extended from text-field:
72
88
  * type="email" - always `email`
@@ -78,13 +94,23 @@ let EmailField = class EmailField extends TextField {
78
94
  ...super.decorateInputMap,
79
95
  type: 'email',
80
96
  inputmode: 'email',
81
- multiple: this.multiple
97
+ multiple: this.multiple,
98
+ pattern: this.pattern
82
99
  };
83
100
  }
84
101
  };
85
102
  __decorate([
86
103
  property({ type: Boolean, reflect: true })
87
104
  ], EmailField.prototype, "multiple", void 0);
105
+ __decorate([
106
+ property({ type: String })
107
+ ], EmailField.prototype, "pattern", void 0);
108
+ __decorate([
109
+ property({ type: Number, attribute: 'maxlength', reflect: true })
110
+ ], EmailField.prototype, "maxLength", void 0);
111
+ __decorate([
112
+ property({ type: Number, attribute: 'minlength', reflect: true })
113
+ ], EmailField.prototype, "minLength", void 0);
88
114
  EmailField = __decorate([
89
115
  customElement('ef-email-field')
90
116
  ], EmailField);
@@ -7,7 +7,6 @@ import { CollectionComposer } from '@refinitiv-ui/utils/collection.js';
7
7
  import '../pill/index.js';
8
8
  import '../text-field/index.js';
9
9
  import { VERSION } from '../version.js';
10
- const hasChanged = (newVal, oldVal) => oldVal === undefined ? false : newVal !== oldVal;
11
10
  /**
12
11
  * An input control component to display a selection of pills
13
12
  *
@@ -551,7 +550,7 @@ __decorate([
551
550
  property({ type: Number, attribute: 'maxlength', reflect: true })
552
551
  ], MultiInput.prototype, "maxLength", void 0);
553
552
  __decorate([
554
- property({ type: Number, attribute: 'minlength', reflect: true, hasChanged })
553
+ property({ type: Number, attribute: 'minlength', reflect: true })
555
554
  ], MultiInput.prototype, "minLength", void 0);
556
555
  __decorate([
557
556
  property({ type: Number, attribute: false })
@@ -288,6 +288,11 @@ export declare class NumberField extends FormFieldElement {
288
288
  * @returns {void}
289
289
  */
290
290
  stepDown(stepIncrement?: number): void;
291
+ /**
292
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
293
+ * @returns true if there is at least one validation constraint
294
+ */
295
+ private shouldValidate;
291
296
  /**
292
297
  * Validate the element input and mark it as error if its input is invalid.
293
298
  * @returns `true` if the element input is valid; otherwise, returns `false`.
@@ -300,37 +305,30 @@ export declare class NumberField extends FormFieldElement {
300
305
  checkValidity(): boolean;
301
306
  /**
302
307
  * @ignore
303
- * @inheritDoc
304
308
  */
305
309
  get selectionStart(): number | null;
306
310
  /**
307
311
  * @ignore
308
- * @inheritDoc
309
312
  */
310
313
  set selectionStart(index: number | null);
311
314
  /**
312
315
  * @ignore
313
- * @inheritDoc
314
316
  */
315
317
  get selectionEnd(): number | null;
316
318
  /**
317
319
  * @ignore
318
- * @inheritDoc
319
320
  */
320
321
  set selectionEnd(index: number | null);
321
322
  /**
322
323
  * @ignore
323
- * @inheritDoc
324
324
  */
325
325
  get selectionDirection(): SelectionDirection | null;
326
326
  /**
327
327
  * @ignore
328
- * @inheritDoc
329
328
  */
330
329
  set selectionDirection(direction: SelectionDirection | null);
331
330
  /**
332
331
  * @ignore
333
- * @inheritDoc
334
332
  */
335
333
  setSelectionRange(startSelection: number | null, endSelection: number | null, selectionDirection?: SelectionDirection): void;
336
334
  /**
@@ -166,7 +166,7 @@ let NumberField = class NumberField extends FormFieldElement {
166
166
  * @returns {void}
167
167
  */
168
168
  update(changedProperties) {
169
- if (changedProperties.has(FocusedPropertyKey) && !this.focused) {
169
+ if (changedProperties.has(FocusedPropertyKey) && !this.focused && this.shouldValidate()) {
170
170
  this.reportValidity();
171
171
  }
172
172
  super.update(changedProperties);
@@ -447,8 +447,9 @@ let NumberField = class NumberField extends FormFieldElement {
447
447
  * @returns {void}
448
448
  */
449
449
  setSilentlyValueAndNotify() {
450
- // Nobody likes to see a red border
451
- this.reportValidity();
450
+ if (this.shouldValidate()) {
451
+ this.reportValidity();
452
+ }
452
453
  const value = this.valueAsNumberString(this.inputValue);
453
454
  if (super.value !== value) {
454
455
  // here we must set the value silently to avoid re-rendering of input
@@ -639,6 +640,16 @@ let NumberField = class NumberField extends FormFieldElement {
639
640
  stepDown(stepIncrement) {
640
641
  this.applyStepDirection(Direction.Down, stepIncrement);
641
642
  }
643
+ /**
644
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
645
+ * @returns true if there is at least one validation constraint
646
+ */
647
+ shouldValidate() {
648
+ const hasMax = this.max !== null;
649
+ const hasMin = this.min !== null;
650
+ const hasStep = this.step !== ANY_STEP;
651
+ return hasMax || hasMin || hasStep;
652
+ }
642
653
  /**
643
654
  * Validate the element input and mark it as error if its input is invalid.
644
655
  * @returns `true` if the element input is valid; otherwise, returns `false`.
@@ -675,7 +686,6 @@ let NumberField = class NumberField extends FormFieldElement {
675
686
  }
676
687
  /**
677
688
  * @ignore
678
- * @inheritDoc
679
689
  */
680
690
  /* c8 ignore start */
681
691
  get selectionStart() {
@@ -684,7 +694,6 @@ let NumberField = class NumberField extends FormFieldElement {
684
694
  /* c8 ignore stop */
685
695
  /**
686
696
  * @ignore
687
- * @inheritDoc
688
697
  */
689
698
  /* c8 ignore start */
690
699
  set selectionStart(index) {
@@ -693,7 +702,6 @@ let NumberField = class NumberField extends FormFieldElement {
693
702
  /* c8 ignore stop */
694
703
  /**
695
704
  * @ignore
696
- * @inheritDoc
697
705
  */
698
706
  /* c8 ignore start */
699
707
  get selectionEnd() {
@@ -702,7 +710,6 @@ let NumberField = class NumberField extends FormFieldElement {
702
710
  /* c8 ignore stop */
703
711
  /**
704
712
  * @ignore
705
- * @inheritDoc
706
713
  */
707
714
  /* c8 ignore start */
708
715
  set selectionEnd(index) {
@@ -711,7 +718,6 @@ let NumberField = class NumberField extends FormFieldElement {
711
718
  /* c8 ignore stop */
712
719
  /**
713
720
  * @ignore
714
- * @inheritDoc
715
721
  */
716
722
  /* c8 ignore start */
717
723
  get selectionDirection() {
@@ -720,7 +726,6 @@ let NumberField = class NumberField extends FormFieldElement {
720
726
  /* c8 ignore stop */
721
727
  /**
722
728
  * @ignore
723
- * @inheritDoc
724
729
  */
725
730
  /* c8 ignore start */
726
731
  set selectionDirection(direction) {
@@ -729,7 +734,6 @@ let NumberField = class NumberField extends FormFieldElement {
729
734
  /* c8 ignore stop */
730
735
  /**
731
736
  * @ignore
732
- * @inheritDoc
733
737
  */
734
738
  /* c8 ignore start */
735
739
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -5,6 +5,16 @@
5
5
  "name": "ef-password-field",
6
6
  "description": "A form control element for password.",
7
7
  "attributes": [
8
+ {
9
+ "name": "maxlength",
10
+ "description": "Set character max limit",
11
+ "type": "number | null"
12
+ },
13
+ {
14
+ "name": "minlength",
15
+ "description": "Set character min limit",
16
+ "type": "number | null"
17
+ },
8
18
  {
9
19
  "name": "disabled",
10
20
  "description": "Set disabled state",
@@ -17,6 +27,12 @@
17
27
  "type": "boolean",
18
28
  "default": "false"
19
29
  },
30
+ {
31
+ "name": "pattern",
32
+ "description": "Set regular expression for input validation",
33
+ "type": "string",
34
+ "default": "\"\""
35
+ },
20
36
  {
21
37
  "name": "placeholder",
22
38
  "description": "Set placeholder text",
@@ -46,19 +62,21 @@
46
62
  "description": "Input's value",
47
63
  "type": "string",
48
64
  "default": "\"\""
49
- },
65
+ }
66
+ ],
67
+ "properties": [
50
68
  {
51
- "name": "maxlength",
69
+ "name": "maxLength",
70
+ "attribute": "maxlength",
52
71
  "description": "Set character max limit",
53
- "type": "number"
72
+ "type": "number | null"
54
73
  },
55
74
  {
56
- "name": "minlength",
75
+ "name": "minLength",
76
+ "attribute": "minlength",
57
77
  "description": "Set character min limit",
58
- "type": "number"
59
- }
60
- ],
61
- "properties": [
78
+ "type": "number | null"
79
+ },
62
80
  {
63
81
  "name": "disabled",
64
82
  "attribute": "disabled",
@@ -73,18 +91,9 @@
73
91
  "type": "boolean",
74
92
  "default": "false"
75
93
  },
76
- {
77
- "name": "maxLength",
78
- "description": "Set character max limit",
79
- "type": "number | null"
80
- },
81
- {
82
- "name": "minLength",
83
- "description": "Set character min limit",
84
- "type": "number | null"
85
- },
86
94
  {
87
95
  "name": "pattern",
96
+ "attribute": "pattern",
88
97
  "description": "Set regular expression for input validation",
89
98
  "type": "string",
90
99
  "default": "\"\""
@@ -2,22 +2,15 @@
2
2
 
3
3
  A form control element for password.
4
4
 
5
- ## Attributes
6
-
7
- | Attribute | Type | Description |
8
- |-------------|----------|-------------------------|
9
- | `maxlength` | `number` | Set character max limit |
10
- | `minlength` | `number` | Set character min limit |
11
-
12
5
  ## Properties
13
6
 
14
7
  | Property | Attribute | Type | Default | Description |
15
8
  |---------------|---------------|------------------|---------|--------------------------------------------------|
16
9
  | `disabled` | `disabled` | `boolean` | false | Set disabled state |
17
10
  | `error` | `error` | `boolean` | false | Set error state |
18
- | `maxLength` | | `number \| null` | null | Set character max limit |
19
- | `minLength` | | `number \| null` | null | Set character min limit |
20
- | `pattern` | | `string` | "" | Set regular expression for input validation |
11
+ | `maxLength` | `maxlength` | `number \| null` | null | Set character max limit |
12
+ | `minLength` | `minlength` | `number \| null` | null | Set character min limit |
13
+ | `pattern` | `pattern` | `string` | "" | Set regular expression for input validation |
21
14
  | `placeholder` | `placeholder` | `string` | "" | Set placeholder text |
22
15
  | `readonly` | `readonly` | `boolean` | false | Set readonly state |
23
16
  | `transparent` | `transparent` | `boolean` | false | Disables all other states and border/background styles. |
@@ -17,12 +17,7 @@ import { TextField } from '../text-field/index.js';
17
17
  * @attr {boolean} error - Set error state
18
18
  * @prop {boolean} [error=false] - Set error state
19
19
  *
20
- * @attr {number} maxlength - Set character max limit
21
- * @prop {number | null} [maxLength=null] - Set character max limit
22
- *
23
- * @attr {number} minlength - Set character min limit
24
- * @prop {number | null} [minLength=null] - Set character min limit
25
- *
20
+ * @attr {string} pattern - Set regular expression for input validation
26
21
  * @prop {string} [pattern=""] - Set regular expression for input validation
27
22
  *
28
23
  * @attr {string} placeholder - Set placeholder text
@@ -41,6 +36,14 @@ import { TextField } from '../text-field/index.js';
41
36
  * @prop {string} [value=""] - Input's value
42
37
  */
43
38
  export declare class PasswordField extends TextField {
39
+ /**
40
+ * Set character max limit
41
+ */
42
+ maxLength: number | null;
43
+ /**
44
+ * Set character min limit
45
+ */
46
+ minLength: number | null;
44
47
  /**
45
48
  * Used for translations
46
49
  */
@@ -1,6 +1,7 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html, unsafeCSS } from '@refinitiv-ui/core';
3
3
  import { customElement } from '@refinitiv-ui/core/decorators/custom-element.js';
4
+ import { property } from '@refinitiv-ui/core/decorators/property.js';
4
5
  import { state } from '@refinitiv-ui/core/decorators/state.js';
5
6
  import '@refinitiv-ui/phrasebook/locale/en/password-field.js';
6
7
  import { translate } from '@refinitiv-ui/translate';
@@ -20,12 +21,7 @@ import { deregisterOverflowTooltip } from '../tooltip/index.js';
20
21
  * @attr {boolean} error - Set error state
21
22
  * @prop {boolean} [error=false] - Set error state
22
23
  *
23
- * @attr {number} maxlength - Set character max limit
24
- * @prop {number | null} [maxLength=null] - Set character max limit
25
- *
26
- * @attr {number} minlength - Set character min limit
27
- * @prop {number | null} [minLength=null] - Set character min limit
28
- *
24
+ * @attr {string} pattern - Set regular expression for input validation
29
25
  * @prop {string} [pattern=""] - Set regular expression for input validation
30
26
  *
31
27
  * @attr {string} placeholder - Set placeholder text
@@ -46,6 +42,16 @@ import { deregisterOverflowTooltip } from '../tooltip/index.js';
46
42
  let PasswordField = class PasswordField extends TextField {
47
43
  constructor() {
48
44
  super(...arguments);
45
+ /**
46
+ * Set character max limit
47
+ */
48
+ // override to merely fix missing attribute from component's doc
49
+ this.maxLength = null;
50
+ /**
51
+ * Set character min limit
52
+ */
53
+ // override to merely fix missing attribute from component's doc
54
+ this.minLength = null;
49
55
  /**
50
56
  * Defines whether password is visible or not
51
57
  */
@@ -150,6 +156,12 @@ let PasswordField = class PasswordField extends TextField {
150
156
  this.isPasswordVisible = !this.isPasswordVisible;
151
157
  }
152
158
  };
159
+ __decorate([
160
+ property({ type: Number, attribute: 'maxlength', reflect: true })
161
+ ], PasswordField.prototype, "maxLength", void 0);
162
+ __decorate([
163
+ property({ type: Number, attribute: 'minlength', reflect: true })
164
+ ], PasswordField.prototype, "minLength", void 0);
153
165
  __decorate([
154
166
  translate({ scope: 'ef-password-field' })
155
167
  ], PasswordField.prototype, "t", void 0);
@@ -5,6 +5,16 @@
5
5
  "name": "ef-search-field",
6
6
  "description": "Form control to get a search input from users.",
7
7
  "attributes": [
8
+ {
9
+ "name": "maxlength",
10
+ "description": "Set character max limit",
11
+ "type": "number | null"
12
+ },
13
+ {
14
+ "name": "minlength",
15
+ "description": "Set character min limit",
16
+ "type": "number | null"
17
+ },
8
18
  {
9
19
  "name": "disabled",
10
20
  "description": "Set disabled state",
@@ -23,6 +33,12 @@
23
33
  "type": "boolean",
24
34
  "default": "false"
25
35
  },
36
+ {
37
+ "name": "pattern",
38
+ "description": "Set regular expression for input validation",
39
+ "type": "string",
40
+ "default": "\"\""
41
+ },
26
42
  {
27
43
  "name": "placeholder",
28
44
  "description": "Set placeholder text",
@@ -57,19 +73,21 @@
57
73
  "name": "icon-has-action",
58
74
  "description": "Specify when icon need to be clickable",
59
75
  "type": "boolean"
60
- },
76
+ }
77
+ ],
78
+ "properties": [
61
79
  {
62
- "name": "maxlength",
80
+ "name": "maxLength",
81
+ "attribute": "maxlength",
63
82
  "description": "Set character max limit",
64
- "type": "number"
83
+ "type": "number | null"
65
84
  },
66
85
  {
67
- "name": "minlength",
86
+ "name": "minLength",
87
+ "attribute": "minlength",
68
88
  "description": "Set character min limit",
69
- "type": "number"
70
- }
71
- ],
72
- "properties": [
89
+ "type": "number | null"
90
+ },
73
91
  {
74
92
  "name": "disabled",
75
93
  "attribute": "disabled",
@@ -91,18 +109,9 @@
91
109
  "type": "boolean",
92
110
  "default": "false"
93
111
  },
94
- {
95
- "name": "maxLength",
96
- "description": "Set character max limit",
97
- "type": "number | null"
98
- },
99
- {
100
- "name": "minLength",
101
- "description": "Set character min limit",
102
- "type": "number | null"
103
- },
104
112
  {
105
113
  "name": "pattern",
114
+ "attribute": "pattern",
106
115
  "description": "Set regular expression for input validation",
107
116
  "type": "string",
108
117
  "default": "\"\""
@@ -7,8 +7,6 @@ Form control to get a search input from users.
7
7
  | Attribute | Type | Description |
8
8
  |-------------------|-----------|----------------------------------------|
9
9
  | `icon-has-action` | `boolean` | Specify when icon need to be clickable |
10
- | `maxlength` | `number` | Set character max limit |
11
- | `minlength` | `number` | Set character min limit |
12
10
 
13
11
  ## Properties
14
12
 
@@ -17,9 +15,9 @@ Form control to get a search input from users.
17
15
  | `disabled` | `disabled` | `boolean` | false | Set disabled state |
18
16
  | `error` | `error` | `boolean` | false | Set error state |
19
17
  | `iconHasAction` | `icon-has-action` | `boolean` | false | Specify when icon need to be clickable |
20
- | `maxLength` | | `number \| null` | null | Set character max limit |
21
- | `minLength` | | `number \| null` | null | Set character min limit |
22
- | `pattern` | | `string` | "" | Set regular expression for input validation |
18
+ | `maxLength` | `maxlength` | `number \| null` | null | Set character max limit |
19
+ | `minLength` | `minlength` | `number \| null` | null | Set character min limit |
20
+ | `pattern` | `pattern` | `string` | "" | Set regular expression for input validation |
23
21
  | `placeholder` | `placeholder` | `string` | "" | Set placeholder text |
24
22
  | `readonly` | `readonly` | `boolean` | false | Set readonly state |
25
23
  | `transparent` | `transparent` | `boolean` | false | Disables all other states and border/background styles. |
@@ -21,12 +21,7 @@ import { TextField } from '../text-field/index.js';
21
21
  * @attr {boolean} icon-has-action - Specify when icon need to be clickable
22
22
  * @prop {boolean} [iconHasAction=false] - Specify when icon need to be clickable
23
23
  *
24
- * @attr {number} maxlength - Set character max limit
25
- * @prop {number | null} [maxLength=null] - Set character max limit
26
- *
27
- * @attr {number} minlength - Set character min limit
28
- * @prop {number | null} [minLength=null] - Set character min limit
29
- *
24
+ * @attr {string} pattern - Set regular expression for input validation
30
25
  * @prop {string} [pattern=""] - Set regular expression for input validation
31
26
  *
32
27
  * @attr {string} placeholder - Set placeholder text
@@ -45,6 +40,14 @@ import { TextField } from '../text-field/index.js';
45
40
  * @prop {string} [value=""] - Input's value
46
41
  */
47
42
  export declare class SearchField extends TextField {
43
+ /**
44
+ * Set character max limit
45
+ */
46
+ maxLength: number | null;
47
+ /**
48
+ * Set character min limit
49
+ */
50
+ minLength: number | null;
48
51
  /**
49
52
  * Used for translations
50
53
  */
@@ -1,6 +1,7 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html, nothing } from '@refinitiv-ui/core';
3
3
  import { customElement } from '@refinitiv-ui/core/decorators/custom-element.js';
4
+ import { property } from '@refinitiv-ui/core/decorators/property.js';
4
5
  import '@refinitiv-ui/phrasebook/locale/en/search-field.js';
5
6
  import { translate } from '@refinitiv-ui/translate';
6
7
  import '../icon/index.js';
@@ -21,12 +22,7 @@ import { TextField } from '../text-field/index.js';
21
22
  * @attr {boolean} icon-has-action - Specify when icon need to be clickable
22
23
  * @prop {boolean} [iconHasAction=false] - Specify when icon need to be clickable
23
24
  *
24
- * @attr {number} maxlength - Set character max limit
25
- * @prop {number | null} [maxLength=null] - Set character max limit
26
- *
27
- * @attr {number} minlength - Set character min limit
28
- * @prop {number | null} [minLength=null] - Set character min limit
29
- *
25
+ * @attr {string} pattern - Set regular expression for input validation
30
26
  * @prop {string} [pattern=""] - Set regular expression for input validation
31
27
  *
32
28
  * @attr {string} placeholder - Set placeholder text
@@ -45,6 +41,19 @@ import { TextField } from '../text-field/index.js';
45
41
  * @prop {string} [value=""] - Input's value
46
42
  */
47
43
  let SearchField = class SearchField extends TextField {
44
+ constructor() {
45
+ super(...arguments);
46
+ /**
47
+ * Set character max limit
48
+ */
49
+ // override to merely fix missing attribute from component's doc
50
+ this.maxLength = null;
51
+ /**
52
+ * Set character min limit
53
+ */
54
+ // override to merely fix missing attribute from component's doc
55
+ this.minLength = null;
56
+ }
48
57
  /**
49
58
  * Decorate `<input>` element with common properties extended from text-field:
50
59
  * type="search" - always `search`
@@ -90,6 +99,12 @@ let SearchField = class SearchField extends TextField {
90
99
  `;
91
100
  }
92
101
  };
102
+ __decorate([
103
+ property({ type: Number, attribute: 'maxlength', reflect: true })
104
+ ], SearchField.prototype, "maxLength", void 0);
105
+ __decorate([
106
+ property({ type: Number, attribute: 'minlength', reflect: true })
107
+ ], SearchField.prototype, "minLength", void 0);
93
108
  __decorate([
94
109
  translate({ scope: 'ef-search-field' })
95
110
  ], SearchField.prototype, "t", void 0);
@@ -8,7 +8,7 @@
8
8
  {
9
9
  "name": "pattern",
10
10
  "description": "Set regular expression for input validation",
11
- "type": "string",
11
+ "type": "string | null",
12
12
  "default": "\"\""
13
13
  },
14
14
  {
@@ -80,7 +80,7 @@
80
80
  "name": "pattern",
81
81
  "attribute": "pattern",
82
82
  "description": "Set regular expression for input validation",
83
- "type": "string",
83
+ "type": "string | null",
84
84
  "default": "\"\""
85
85
  },
86
86
  {
@@ -12,7 +12,7 @@ Form control element for text.
12
12
  | `iconHasAction` | `icon-has-action` | `boolean` | false | Specify when icon need to be clickable |
13
13
  | `maxLength` | `maxlength` | `number \| null` | null | Set character max limit |
14
14
  | `minLength` | `minlength` | `number \| null` | null | Set character min limit |
15
- | `pattern` | `pattern` | `string` | "" | Set regular expression for input validation |
15
+ | `pattern` | `pattern` | `string \| null` | "" | Set regular expression for input validation |
16
16
  | `placeholder` | `placeholder` | `string` | "" | Set placeholder text |
17
17
  | `readonly` | `readonly` | `boolean` | false | Set readonly state |
18
18
  | `transparent` | `transparent` | `boolean` | false | Disables all other states and border/background styles. |
@@ -45,7 +45,7 @@ export declare class TextField extends FormFieldElement {
45
45
  /**
46
46
  * Set regular expression for input validation
47
47
  */
48
- pattern: string;
48
+ pattern: string | null;
49
49
  /**
50
50
  * Specify icon to display in input. Value can be icon name
51
51
  */
@@ -80,6 +80,11 @@ export declare class TextField extends FormFieldElement {
80
80
  * @returns shouldUpdate
81
81
  */
82
82
  protected updated(changedProperties: PropertyValues): void;
83
+ /**
84
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
85
+ * @returns true if there is at least one validation constraint
86
+ */
87
+ protected shouldValidate(): boolean;
83
88
  /**
84
89
  * Returns `true` if the element input is valid; otherwise, returns `false`.
85
90
  * @returns element input validity
@@ -6,7 +6,6 @@ import { isElementOverflown } from '@refinitiv-ui/utils/element.js';
6
6
  import '../icon/index.js';
7
7
  import { registerOverflowTooltip } from '../tooltip/index.js';
8
8
  import { VERSION } from '../version.js';
9
- const hasChanged = (newVal, oldVal) => oldVal === undefined ? false : newVal !== oldVal;
10
9
  /**
11
10
  * Form control element for text.
12
11
  *
@@ -114,7 +113,7 @@ let TextField = class TextField extends FormFieldElement {
114
113
  * @returns {void}
115
114
  */
116
115
  update(changedProperties) {
117
- if (changedProperties.has(FocusedPropertyKey) && !this.focused) {
116
+ if (changedProperties.has(FocusedPropertyKey) && !this.focused && this.shouldValidate()) {
118
117
  this.reportValidity();
119
118
  }
120
119
  super.update(changedProperties);
@@ -130,6 +129,16 @@ let TextField = class TextField extends FormFieldElement {
130
129
  this.syncInputValue();
131
130
  }
132
131
  }
132
+ /**
133
+ * Returns whether input of the element should be validated or not based on the existence of validation constraints
134
+ * @returns true if there is at least one validation constraint
135
+ */
136
+ shouldValidate() {
137
+ const hasMaxLength = this.maxLength !== null;
138
+ const hasMinLength = this.minLength !== null;
139
+ const hasPattern = !!this.pattern;
140
+ return hasMaxLength || hasMinLength || hasPattern;
141
+ }
133
142
  /**
134
143
  * Returns `true` if the element input is valid; otherwise, returns `false`.
135
144
  * @returns element input validity
@@ -186,7 +195,9 @@ let TextField = class TextField extends FormFieldElement {
186
195
  onPossibleValueChange(event) {
187
196
  const value = this.inputElement?.value || '';
188
197
  this.setValueAndNotify(value);
189
- this.reportValidity();
198
+ if (this.shouldValidate()) {
199
+ this.reportValidity();
200
+ }
190
201
  }
191
202
  /**
192
203
  * Fires event on `icon` click
@@ -246,7 +257,7 @@ let TextField = class TextField extends FormFieldElement {
246
257
  }
247
258
  };
248
259
  __decorate([
249
- property({ type: String, hasChanged })
260
+ property({ type: String })
250
261
  ], TextField.prototype, "pattern", void 0);
251
262
  __decorate([
252
263
  property({ type: String, reflect: true })
@@ -258,7 +269,7 @@ __decorate([
258
269
  property({ type: Number, attribute: 'maxlength', reflect: true })
259
270
  ], TextField.prototype, "maxLength", void 0);
260
271
  __decorate([
261
- property({ type: Number, attribute: 'minlength', reflect: true, hasChanged })
272
+ property({ type: Number, attribute: 'minlength', reflect: true })
262
273
  ], TextField.prototype, "minLength", void 0);
263
274
  TextField = __decorate([
264
275
  customElement('ef-text-field')
@@ -1,3 +1,4 @@
1
+ import escapeStringRegexp from 'escape-string-regexp';
1
2
  /**
2
3
  * Default filter used by tree
3
4
  * @param el Tree instance to filter
@@ -14,7 +15,7 @@ export const defaultFilter = (el) => {
14
15
  const getRegularExpressionOfQuery = () => {
15
16
  if (el.query !== query || !queryRegExp) {
16
17
  query = el.query || '';
17
- queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
18
+ queryRegExp = new RegExp(escapeStringRegexp(query), 'i');
18
19
  }
19
20
  return queryRegExp;
20
21
  };
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '7.8.0';
1
+ export const VERSION = '7.9.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refinitiv-ui/elements",
3
- "version": "7.8.0",
3
+ "version": "7.9.0",
4
4
  "description": "Element Framework Elements",
5
5
  "author": "LSEG",
6
6
  "license": "Apache-2.0",
@@ -348,29 +348,30 @@
348
348
  "chartjs-adapter-date-fns": "^3.0.0",
349
349
  "d3-interpolate": "^3.0.1",
350
350
  "date-fns": "^2.29.3",
351
+ "escape-string-regexp": "^5.0.0",
351
352
  "lightweight-charts": "^4.1.0",
352
353
  "tslib": "^2.3.1"
353
354
  },
354
355
  "devDependencies": {
355
- "@refinitiv-ui/core": "^7.3.0",
356
- "@refinitiv-ui/demo-block": "^7.1.0",
356
+ "@refinitiv-ui/core": "^7.4.0",
357
+ "@refinitiv-ui/demo-block": "^7.1.1",
357
358
  "@refinitiv-ui/i18n": "^7.1.0",
358
359
  "@refinitiv-ui/phrasebook": "^7.1.0",
359
360
  "@refinitiv-ui/test-helpers": "^7.1.0",
360
- "@refinitiv-ui/translate": "^7.1.0",
361
+ "@refinitiv-ui/translate": "^7.1.1",
361
362
  "@refinitiv-ui/utils": "^7.2.0",
362
363
  "@types/d3-interpolate": "^3.0.1"
363
364
  },
364
365
  "peerDependencies": {
365
366
  "@refinitiv-ui/browser-sparkline": "^1.0.0 || ^2.0.0",
366
- "@refinitiv-ui/core": "^7.3.0",
367
+ "@refinitiv-ui/core": "^7.4.0",
367
368
  "@refinitiv-ui/i18n": "^7.1.0",
368
369
  "@refinitiv-ui/phrasebook": "^7.1.0",
369
- "@refinitiv-ui/translate": "^7.1.0",
370
+ "@refinitiv-ui/translate": "^7.1.1",
370
371
  "@refinitiv-ui/utils": "^7.2.0"
371
372
  },
372
373
  "publishConfig": {
373
374
  "access": "public"
374
375
  },
375
- "gitHead": "f0019ccc2f241a998c5e455b433c0e36720d5fe6"
376
+ "gitHead": "fd69344454e78b14bb7ecd5ddb4d9286e60e4c95"
376
377
  }