@ons/design-system 72.10.6 → 72.10.7
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/components/char-check-limit/_macro.njk +5 -4
- package/components/char-check-limit/_macro.spec.js +167 -7
- package/components/char-check-limit/character-check.js +23 -17
- package/components/char-check-limit/character-check.spec.js +106 -1
- package/components/chart/_chart.scss +33 -5
- package/components/chart/_macro.njk +169 -149
- package/components/chart/_macro.spec.js +215 -21
- package/components/chart/annotations-options.js +1 -1
- package/components/chart/bar-chart.js +1 -0
- package/components/chart/chart-iframe-resize.dom.js +8 -0
- package/components/chart/chart-iframe-resize.js +16 -0
- package/components/chart/chart.js +5 -0
- package/components/chart/example-bar-chart.njk +4 -0
- package/components/chart/example-iframe-chart.njk +32 -0
- package/components/chart/example-line-chart-with-annotations.njk +3 -1
- package/components/chart/example-line-chart.njk +4 -0
- package/components/chart/example-scatter-chart.njk +4 -0
- package/components/chart/range-annotations-options.js +1 -1
- package/components/chart/reference-line-annotations-options.js +1 -1
- package/components/checkboxes/_macro.spec.js +3 -3
- package/components/input/_macro.njk +1 -2
- package/components/input/_macro.spec.js +2 -22
- package/components/input/example-input-search-with-character-check.njk +0 -1
- package/components/textarea/_macro.njk +19 -3
- package/components/textarea/_macro.spec.js +76 -3
- package/components/textarea/example-textarea-with-word-limit.njk +20 -0
- package/css/main.css +1 -1
- package/js/main.js +2 -0
- package/package.json +3 -2
- package/scripts/main.es5.js +3 -1
- package/scripts/main.js +3 -1
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
<span
|
|
7
7
|
id="{{ params.id }}"
|
|
8
8
|
class="ons-input__limit ons-u-fs-s--b ons-u-d-no ons-u-mt-2xs"
|
|
9
|
-
data-
|
|
10
|
-
data-
|
|
11
|
-
data-
|
|
12
|
-
data-
|
|
9
|
+
data-count-type="{{ params.variant if params.variant == 'word' else 'char' }}"
|
|
10
|
+
data-message-singular="{% if params.variant == 'word' %}{{ params.wordCountSingular }}{% else %}{{ params.charCountSingular }}{% endif %}"
|
|
11
|
+
data-message-plural="{% if params.variant == 'word' %}{{ params.wordCountPlural }}{% else %}{{ params.charCountPlural }}{% endif %}"
|
|
12
|
+
data-message-over-limit-singular="{% if params.variant == 'word' %}{{ params.wordCountOverLimitSingular | default("You have exceeded the word limit by {x} word") }}{% else %}{{ params.charCountOverLimitSingular | default("You have exceeded the character limit by {x} character") }}{% endif %}"
|
|
13
|
+
data-message-over-limit-plural="{% if params.variant == 'word' %}{{ params.wordCountOverLimitPlural | default("You have exceeded the word limit by {x} words") }}{% else %}{{ params.charCountOverLimitPlural | default("You have exceeded the character limit by {x} characters") }}{% endif %}"
|
|
13
14
|
>
|
|
14
15
|
</span>
|
|
15
16
|
{% endmacro %}
|
|
@@ -5,7 +5,7 @@ import * as cheerio from 'cheerio';
|
|
|
5
5
|
import axe from '../../tests/helpers/axe';
|
|
6
6
|
import { renderComponent } from '../../tests/helpers/rendering';
|
|
7
7
|
|
|
8
|
-
import { EXAMPLE_CHAR_CHECK_LIMIT } from './_test-examples';
|
|
8
|
+
import { EXAMPLE_CHAR_CHECK_LIMIT, EXAMPLE_WORD_CHECK_LIMIT, EXAMPLE_CHAR_WORD_CHECK_LIMIT_MESSAGES } from './_test-examples';
|
|
9
9
|
|
|
10
10
|
describe('FOR: Macro: CharCheckLimit', () => {
|
|
11
11
|
describe('GIVEN: Params: Required', () => {
|
|
@@ -17,26 +17,34 @@ describe('FOR: Macro: CharCheckLimit', () => {
|
|
|
17
17
|
|
|
18
18
|
expect(results).toHaveNoViolations();
|
|
19
19
|
});
|
|
20
|
+
|
|
21
|
+
test('THEN: sets char as the count type to count number of characters', () => {
|
|
22
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('char');
|
|
23
|
+
});
|
|
24
|
+
|
|
20
25
|
test('THEN: has the provided id attribute', () => {
|
|
21
26
|
expect($('.ons-input__limit').attr('id')).toBe('example-char-check-limit');
|
|
22
27
|
});
|
|
28
|
+
|
|
23
29
|
test('THEN: has the data attribute which defines charCountPlural', () => {
|
|
24
|
-
expect($('.ons-input__limit').attr('data-
|
|
30
|
+
expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} characters remaining');
|
|
25
31
|
});
|
|
32
|
+
|
|
26
33
|
test('THEN: has the data attribute which defines charCountSingular', () => {
|
|
27
|
-
expect($('.ons-input__limit').attr('data-
|
|
34
|
+
expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} character remaining');
|
|
28
35
|
});
|
|
29
36
|
test('THEN: has the data attribute which defines charCountOverLimitSingular', () => {
|
|
30
|
-
expect($('.ons-input__limit').attr('data-
|
|
37
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-singular')).toBe('{x} character too many');
|
|
31
38
|
});
|
|
39
|
+
|
|
32
40
|
test('THEN: has the data attribute which defines charCountOverLimitPlural', () => {
|
|
33
|
-
expect($('.ons-input__limit').attr('data-
|
|
41
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-plural')).toBe('{x} characters too many');
|
|
34
42
|
});
|
|
35
43
|
});
|
|
36
44
|
});
|
|
37
45
|
|
|
38
46
|
describe('GIVEN: Params: variant', () => {
|
|
39
|
-
describe('WHEN: variant is
|
|
47
|
+
describe('WHEN: variant is set to check', () => {
|
|
40
48
|
const $ = cheerio.load(
|
|
41
49
|
renderComponent(
|
|
42
50
|
'char-check-limit',
|
|
@@ -48,7 +56,7 @@ describe('FOR: Macro: CharCheckLimit', () => {
|
|
|
48
56
|
),
|
|
49
57
|
);
|
|
50
58
|
|
|
51
|
-
test('THEN: passes jest-axe checks
|
|
59
|
+
test('THEN: passes jest-axe checks', async () => {
|
|
52
60
|
const results = await axe($.html());
|
|
53
61
|
expect(results).toHaveNoViolations();
|
|
54
62
|
});
|
|
@@ -56,6 +64,158 @@ describe('FOR: Macro: CharCheckLimit', () => {
|
|
|
56
64
|
test('THEN: renders the passed content', () => {
|
|
57
65
|
expect($('.ons-js-char-check-input').text()).toBe('Test content.');
|
|
58
66
|
});
|
|
67
|
+
|
|
68
|
+
test('THEN: sets char as the count type to count number of characters', () => {
|
|
69
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('char');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('WHEN: variant is set to word', () => {
|
|
74
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_WORD_CHECK_LIMIT));
|
|
75
|
+
|
|
76
|
+
test('THEN: passes jest-axe checks', async () => {
|
|
77
|
+
const results = await axe($.html());
|
|
78
|
+
expect(results).toHaveNoViolations();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('THEN: sets word as the count type to count number of words', () => {
|
|
82
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('word');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('THEN: has the data attribute which defines wordCountPlural', () => {
|
|
86
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_WORD_CHECK_LIMIT));
|
|
87
|
+
expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} words remaining');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('THEN: has the data attribute which defines wordCountSingular', () => {
|
|
91
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_WORD_CHECK_LIMIT));
|
|
92
|
+
expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} word remaining');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('THEN: has the data attribute which defines wordCountOverLimitPlural', () => {
|
|
96
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_WORD_CHECK_LIMIT));
|
|
97
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-plural')).toBe('You have {x} words too many');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('THEN: has the data attribute which defines wordCountOverLimitSingular', () => {
|
|
101
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_WORD_CHECK_LIMIT));
|
|
102
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-singular')).toBe('You have {x} word too many');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('GIVEN: Params: Character and Word count messages', () => {
|
|
108
|
+
describe('WHEN: character and word count messages are provided', () => {
|
|
109
|
+
const $ = cheerio.load(renderComponent('char-check-limit', EXAMPLE_CHAR_WORD_CHECK_LIMIT_MESSAGES));
|
|
110
|
+
|
|
111
|
+
test('THEN: passes jest-axe checks', async () => {
|
|
112
|
+
const results = await axe($.html());
|
|
113
|
+
|
|
114
|
+
expect(results).toHaveNoViolations();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test('THEN: sets char as the count type to count number of characters', () => {
|
|
118
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('char');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test('THEN: has the provided id attribute', () => {
|
|
122
|
+
expect($('.ons-input__limit').attr('id')).toBe('example-char-word-check-limit');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('THEN: has the data attribute which defines charCountPlural', () => {
|
|
126
|
+
expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} characters remaining');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('THEN: has the data attribute which defines charCountSingular', () => {
|
|
130
|
+
expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} character remaining');
|
|
131
|
+
});
|
|
132
|
+
test('THEN: has the data attribute which defines charCountOverLimitSingular', () => {
|
|
133
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-singular')).toBe('You have {x} character too many');
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('THEN: has the data attribute which defines charCountOverLimitPlural', () => {
|
|
137
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-plural')).toBe('You have {x} characters too many');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('WHEN: character and word count messages are provided and variant is set to check', () => {
|
|
142
|
+
const $ = cheerio.load(
|
|
143
|
+
renderComponent(
|
|
144
|
+
'char-check-limit',
|
|
145
|
+
{
|
|
146
|
+
...EXAMPLE_CHAR_WORD_CHECK_LIMIT_MESSAGES,
|
|
147
|
+
variant: 'check',
|
|
148
|
+
},
|
|
149
|
+
['<p>Test content.</p>'],
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
test('THEN: passes jest-axe checks', async () => {
|
|
154
|
+
const results = await axe($.html());
|
|
155
|
+
|
|
156
|
+
expect(results).toHaveNoViolations();
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test('THEN: sets char as the count type to count number of characters', () => {
|
|
160
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('char');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('THEN: has the provided id attribute', () => {
|
|
164
|
+
expect($('.ons-input__limit').attr('id')).toBe('example-char-word-check-limit');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('THEN: has the data attribute which defines charCountPlural', () => {
|
|
168
|
+
expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} characters remaining');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('THEN: has the data attribute which defines charCountSingular', () => {
|
|
172
|
+
expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} character remaining');
|
|
173
|
+
});
|
|
174
|
+
test('THEN: has the data attribute which defines charCountOverLimitSingular', () => {
|
|
175
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-singular')).toBe('You have {x} character too many');
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('THEN: has the data attribute which defines charCountOverLimitPlural', () => {
|
|
179
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-plural')).toBe('You have {x} characters too many');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe('WHEN: character and word count messages are provided and variant is set to word', () => {
|
|
184
|
+
const $ = cheerio.load(
|
|
185
|
+
renderComponent('char-check-limit', {
|
|
186
|
+
...EXAMPLE_CHAR_WORD_CHECK_LIMIT_MESSAGES,
|
|
187
|
+
variant: 'word',
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
test('THEN: passes jest-axe checks', async () => {
|
|
192
|
+
const results = await axe($.html());
|
|
193
|
+
|
|
194
|
+
expect(results).toHaveNoViolations();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test('THEN: sets char as the count type to count number of words', () => {
|
|
198
|
+
expect($('.ons-input__limit').attr('data-count-type')).toBe('word');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('THEN: has the provided id attribute', () => {
|
|
202
|
+
expect($('.ons-input__limit').attr('id')).toBe('example-char-word-check-limit');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('THEN: has the data attribute which defines wordCountPlural', () => {
|
|
206
|
+
expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} words remaining');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test('THEN: has the data attribute which defines wordCountSingular', () => {
|
|
210
|
+
expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} word remaining');
|
|
211
|
+
});
|
|
212
|
+
test('THEN: has the data attribute which defines wordCountOverLimitSingular', () => {
|
|
213
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-singular')).toBe('You have {x} word too many');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
test('THEN: has the data attribute which defines wordCountOverLimitPlural', () => {
|
|
217
|
+
expect($('.ons-input__limit').attr('data-message-over-limit-plural')).toBe('You have {x} words too many');
|
|
218
|
+
});
|
|
59
219
|
});
|
|
60
220
|
});
|
|
61
221
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const inputClassLimitReached = 'ons-input--limit-reached';
|
|
2
2
|
const remainingClassLimitReached = 'ons-input__limit--reached';
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const attrMessageCheckRef = 'data-message-check-ref';
|
|
4
|
+
const attrMessageCheckVal = 'data-message-check-num';
|
|
5
|
+
const countType = 'data-count-type';
|
|
6
6
|
|
|
7
7
|
export default class CharCheck {
|
|
8
8
|
constructor(context) {
|
|
@@ -18,13 +18,12 @@ export default class CharCheck {
|
|
|
18
18
|
// Find the button: if input is passed directly, look at its parent
|
|
19
19
|
let parent = this.input.parentNode;
|
|
20
20
|
this.button = parent ? parent.querySelector('button') : null;
|
|
21
|
-
this.checkElement = document.getElementById(this.input.getAttribute(
|
|
22
|
-
this.checkVal = this.input.getAttribute(
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
this.
|
|
27
|
-
this.charLimitPluralMessage = this.checkElement.getAttribute('data-charcount-limit-plural') || null;
|
|
21
|
+
this.checkElement = document.getElementById(this.input.getAttribute(attrMessageCheckRef));
|
|
22
|
+
this.checkVal = this.input.getAttribute(attrMessageCheckVal);
|
|
23
|
+
this.singularMessage = this.checkElement.getAttribute('data-message-singular') || null;
|
|
24
|
+
this.pluralMessage = this.checkElement.getAttribute('data-message-plural') || null;
|
|
25
|
+
this.overLimitSingularMessage = this.checkElement.getAttribute('data-message-over-limit-singular') || null;
|
|
26
|
+
this.overLimitPluralMessage = this.checkElement.getAttribute('data-message-over-limit-plural') || null;
|
|
28
27
|
|
|
29
28
|
this.updateCheckReadout(this.input);
|
|
30
29
|
|
|
@@ -37,7 +36,8 @@ export default class CharCheck {
|
|
|
37
36
|
|
|
38
37
|
updateCheckReadout(event, firstRun) {
|
|
39
38
|
const value = this.input.value;
|
|
40
|
-
const
|
|
39
|
+
const currentLength = this.checkElement.getAttribute(countType) == 'char' ? this.getCharLength(value) : this.getWordLength(value);
|
|
40
|
+
const remaining = this.checkVal - currentLength;
|
|
41
41
|
|
|
42
42
|
// Prevent aria live announcement when component initialises
|
|
43
43
|
if (!firstRun && event.inputType) {
|
|
@@ -53,12 +53,12 @@ export default class CharCheck {
|
|
|
53
53
|
|
|
54
54
|
checkRemaining(remaining) {
|
|
55
55
|
let message;
|
|
56
|
-
if (
|
|
56
|
+
if (remaining === 1) {
|
|
57
57
|
message = this.singularMessage;
|
|
58
58
|
} else if (remaining === -1) {
|
|
59
|
-
message = this.
|
|
59
|
+
message = this.overLimitSingularMessage;
|
|
60
60
|
} else if (remaining < -1) {
|
|
61
|
-
message = this.
|
|
61
|
+
message = this.overLimitPluralMessage;
|
|
62
62
|
} else {
|
|
63
63
|
message = this.pluralMessage;
|
|
64
64
|
}
|
|
@@ -82,9 +82,7 @@ export default class CharCheck {
|
|
|
82
82
|
// Always display the remaining character message for textarea
|
|
83
83
|
this.checkElement.classList['remove']('ons-u-d-no');
|
|
84
84
|
} else {
|
|
85
|
-
this.checkElement.classList[(remaining < this.checkVal && remaining > 0
|
|
86
|
-
'ons-u-d-no',
|
|
87
|
-
);
|
|
85
|
+
this.checkElement.classList[(remaining < this.checkVal && remaining > 0) || remaining < 0 ? 'remove' : 'add']('ons-u-d-no');
|
|
88
86
|
}
|
|
89
87
|
}
|
|
90
88
|
|
|
@@ -97,4 +95,12 @@ export default class CharCheck {
|
|
|
97
95
|
const lineBreaks = (text.match(/\n/g) || []).length;
|
|
98
96
|
return text.length + lineBreaks;
|
|
99
97
|
}
|
|
98
|
+
|
|
99
|
+
getWordLength(text) {
|
|
100
|
+
return text
|
|
101
|
+
.trim()
|
|
102
|
+
.split(/\s+/) // split by any whitespace
|
|
103
|
+
.map((word) => word.replace(/[.,!?;:]+$/, '')) // remove trailing punctuation
|
|
104
|
+
.filter(Boolean).length;
|
|
105
|
+
}
|
|
100
106
|
}
|
|
@@ -11,7 +11,6 @@ const EXAMPLE_INPUT_WITH_CHARACTER_CHECK = {
|
|
|
11
11
|
text: 'Filter',
|
|
12
12
|
},
|
|
13
13
|
charCheckLimit: {
|
|
14
|
-
charcheckCountdown: true,
|
|
15
14
|
limit: 11,
|
|
16
15
|
charCountOverLimitSingular: '{x} number too many',
|
|
17
16
|
charCountOverLimitPlural: '{x} numbers too many',
|
|
@@ -51,6 +50,23 @@ const EXAMPLE_CHARACTER_CHECK_WITH_MUTUALLY_EXCLUSIVE = {
|
|
|
51
50
|
},
|
|
52
51
|
};
|
|
53
52
|
|
|
53
|
+
const EXAMPLE_INPUT_WITH_WORD_CHECK = {
|
|
54
|
+
id: 'example-textarea',
|
|
55
|
+
name: 'feedback-limited',
|
|
56
|
+
width: '30',
|
|
57
|
+
label: {
|
|
58
|
+
text: 'Please provide some feedback',
|
|
59
|
+
description: 'For example describe any difficulties you experienced in the use of this service',
|
|
60
|
+
},
|
|
61
|
+
wordCheckLimit: {
|
|
62
|
+
limit: 5,
|
|
63
|
+
wordCountSingular: 'You have {x} word remaining',
|
|
64
|
+
wordCountPlural: 'You have {x} words remaining',
|
|
65
|
+
wordCountOverLimitSingular: 'You are {x} word over the limit',
|
|
66
|
+
wordCountOverLimitPlural: 'You are {x} words over the limit',
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
54
70
|
describe('script: character-check', () => {
|
|
55
71
|
describe('mode: basic', () => {
|
|
56
72
|
beforeEach(async () => {
|
|
@@ -197,4 +213,93 @@ describe('script: character-check', () => {
|
|
|
197
213
|
});
|
|
198
214
|
});
|
|
199
215
|
});
|
|
216
|
+
|
|
217
|
+
describe('Word limit', () => {
|
|
218
|
+
beforeEach(async () => {
|
|
219
|
+
await setTestPage('/test', renderComponent('textarea', EXAMPLE_INPUT_WITH_WORD_CHECK));
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('Given that the word limit helper has initialised correctly', () => {
|
|
223
|
+
it('the word limit readout should be visible', async () => {
|
|
224
|
+
const hasClass = await page.$eval('#example-textarea-check', (node) => node.classList.contains('ons-u-d-no'));
|
|
225
|
+
expect(hasClass).toBe(false);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe('Given that the user has not typed into the textarea', () => {
|
|
230
|
+
describe('when the user types into the textarea', () => {
|
|
231
|
+
beforeEach(async () => {
|
|
232
|
+
await page.type('#example-textarea', 'Lorem ipsum dolor');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('then the word limit helper text reflects the number of words remaining', async () => {
|
|
236
|
+
const readout = await page.$eval('#example-textarea-check', (node) => node.textContent);
|
|
237
|
+
expect(readout).toBe('You have 2 words remaining');
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe('when the user reaches the maxlength of the textarea', () => {
|
|
242
|
+
beforeEach(async () => {
|
|
243
|
+
await page.type('#example-textarea', 'Lorem ipsum dolor sit amet');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('then the word limit helper text reflects the number of words remaining', async () => {
|
|
247
|
+
const readout = await page.$eval('#example-textarea-check', (node) => node.textContent);
|
|
248
|
+
expect(readout).toBe('You have 0 words remaining');
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
describe('when the user exceeds the maxlength of the textarea', () => {
|
|
253
|
+
beforeEach(async () => {
|
|
254
|
+
await page.type('#example-textarea', 'Lorem ipsum dolor sit amet, consectetur porttitor.');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('then the word limit helper text reflects the number of words exceeded', async () => {
|
|
258
|
+
const readout = await page.$eval('#example-textarea-check', (node) => node.textContent);
|
|
259
|
+
expect(readout).toBe('You are 2 words over the limit');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('then the textarea should be given limit reached classes', async () => {
|
|
263
|
+
const hasClass = await page.$eval('#example-textarea', (node) => node.classList.contains('ons-input--limit-reached'));
|
|
264
|
+
expect(hasClass).toBe(true);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('then the word limit helper text should be given limit reached classes', async () => {
|
|
268
|
+
const hasClass = await page.$eval('#example-textarea-check', (node) =>
|
|
269
|
+
node.classList.contains('ons-input__limit--reached'),
|
|
270
|
+
);
|
|
271
|
+
expect(hasClass).toBe(true);
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('Given that the user has reached the maxlength of the textarea', () => {
|
|
276
|
+
beforeEach(async () => {
|
|
277
|
+
await page.type('#example-textarea', 'Lorem ipsum dolor sit a');
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
describe('when the user removes a character', () => {
|
|
281
|
+
beforeEach(async () => {
|
|
282
|
+
await page.focus('#example-textarea');
|
|
283
|
+
await page.keyboard.press('Backspace');
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('then the word limit helper text reflects the number of words remaining', async () => {
|
|
287
|
+
const readout = await page.$eval('#example-textarea-check', (node) => node.textContent);
|
|
288
|
+
expect(readout).toBe('You have 1 word remaining');
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('then the textarea should not be given limit reached classes', async () => {
|
|
292
|
+
const hasClass = await page.$eval('#example-textarea', (node) => node.classList.contains('ons-input--limit-reached'));
|
|
293
|
+
expect(hasClass).toBe(false);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('then the readout should not be given limit reached classes', async () => {
|
|
297
|
+
const hasClass = await page.$eval('#example-textarea-check', (node) =>
|
|
298
|
+
node.classList.contains('ons-input__limit--reached'),
|
|
299
|
+
);
|
|
300
|
+
expect(hasClass).toBe(false);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
});
|
|
200
305
|
});
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
container-type: inline-size;
|
|
4
4
|
max-width: $grid-max-width;
|
|
5
5
|
|
|
6
|
+
&__chart {
|
|
7
|
+
overflow: visible !important;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
&__download-title {
|
|
7
11
|
@extend .ons-u-pt-l;
|
|
8
12
|
@extend .ons-u-fs-r--b;
|
|
@@ -12,7 +16,7 @@
|
|
|
12
16
|
color: var(--ons-color-grey-75);
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
&
|
|
19
|
+
&__annotations-footnotes-number {
|
|
16
20
|
// !important is necessary for some range annotation labels at mobile, otherwise
|
|
17
21
|
// the inline-styled block display takes precedence. This inline style is only
|
|
18
22
|
// applied in some cases - it seems to happen when the shaded area is narrower than the label width.
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
/* Override Highcharts styling */
|
|
37
|
-
&
|
|
41
|
+
&__annotations-footnotes-number span {
|
|
38
42
|
position: static !important;
|
|
39
43
|
transform-origin: 0 0 !important;
|
|
40
44
|
font-size: inherit !important;
|
|
@@ -43,7 +47,7 @@
|
|
|
43
47
|
left: 0 !important;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
&
|
|
50
|
+
&__annotations-footnotes {
|
|
47
51
|
list-style: none;
|
|
48
52
|
padding: 0;
|
|
49
53
|
margin: 0 0 1rem;
|
|
@@ -56,12 +60,14 @@
|
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
&
|
|
63
|
+
&__annotations-footnotes_item {
|
|
60
64
|
display: flex;
|
|
61
|
-
align-items:
|
|
65
|
+
align-items: flex-start;
|
|
62
66
|
gap: 0.5rem;
|
|
63
67
|
font-size: 0.875rem; // 14px
|
|
64
68
|
color: var(--ons-color-grey-100);
|
|
69
|
+
line-height: 1.2rem;
|
|
70
|
+
margin-bottom: 0.5rem;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
&__boxplot-legend {
|
|
@@ -95,6 +101,15 @@
|
|
|
95
101
|
font-size: inherit;
|
|
96
102
|
}
|
|
97
103
|
}
|
|
104
|
+
|
|
105
|
+
&__iframe {
|
|
106
|
+
width: 100%;
|
|
107
|
+
|
|
108
|
+
@media (scripting: none) {
|
|
109
|
+
// Approximately matches the aspect ratio of the fallback image inside the iframe
|
|
110
|
+
aspect-ratio: 16 / 9;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
98
113
|
}
|
|
99
114
|
|
|
100
115
|
// This is a workaround to position the axis title to the left
|
|
@@ -148,3 +163,16 @@
|
|
|
148
163
|
border-top: 1px solid var(--ons-color-grey-100);
|
|
149
164
|
border-left: 1px solid var(--ons-color-grey-100);
|
|
150
165
|
}
|
|
166
|
+
|
|
167
|
+
// Allow last label to overflow
|
|
168
|
+
.highcharts-container {
|
|
169
|
+
overflow: visible !important;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.highcharts-xaxis-labels span:last-child {
|
|
173
|
+
overflow: visible !important;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.bar-chart-container .highcharts-yaxis-labels span:last-child {
|
|
177
|
+
overflow: visible !important;
|
|
178
|
+
}
|