@ons/design-system 73.2.0 → 73.4.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/components/button/_button.scss +3 -6
- package/components/chart/annotations-options.js +15 -3
- package/components/chart/chart.js +27 -2
- package/components/chart/common-chart-options.js +10 -0
- package/components/chart/range-annotations-options.js +19 -3
- package/components/chart/reference-line-annotations-options.js +19 -0
- package/components/description-list/_description-list.scss +26 -0
- package/components/header/_header.scss +47 -4
- package/components/header/_macro.njk +168 -185
- package/components/header/_macro.spec.js +116 -14
- package/components/header/example-header-basic-with-search-no-heading.njk +22 -0
- package/components/header/header.spec.js +18 -1
- package/components/hero/example-hero-grey-with-last-updated.njk +27 -0
- package/components/navigation/navigation.js +20 -2
- package/components/navigation/navigation.spec.js +22 -0
- package/components/phase-banner/_macro.njk +10 -1
- package/components/phase-banner/_macro.spec.js +27 -0
- package/components/phase-banner/example-phase-banner-beta-with-feedback-link.njk +18 -0
- package/components/phase-banner/example-phase-banner-beta-without-feedback-link.njk +7 -0
- package/components/question/_question.scss +1 -0
- package/components/table/_macro.njk +6 -3
- package/components/table/_macro.spec.js +58 -0
- package/components/table/_table.scss +9 -1
- package/components/table/example-table-with-valign-property.njk +142 -0
- package/css/main.css +1 -1
- package/layout/_template.njk +1 -1
- package/package.json +1 -1
- package/scripts/main.es5.js +1 -1
- package/scripts/main.js +2 -2
- package/scss/utilities/_highlight.scss +6 -2
- package/scss/utilities/_typography.scss +4 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
2
2
|
import { EXAMPLE_HEADER_SEARCH_AND_MENU_LINKS } from './_test-examples';
|
|
3
|
-
import { getNodeAttributes } from '../../tests/helpers/puppeteer';
|
|
3
|
+
import { getNodeAttributes, setViewport } from '../../tests/helpers/puppeteer';
|
|
4
4
|
|
|
5
5
|
describe('script: header', () => {
|
|
6
6
|
beforeEach(async () => {
|
|
@@ -107,6 +107,23 @@ describe('script: header', () => {
|
|
|
107
107
|
const isAriaHiddenFalse = await page.$eval('.ons-header-nav-menu', (el) => el.getAttribute('aria-hidden') === 'false');
|
|
108
108
|
expect(isAriaHiddenFalse).toBe(true);
|
|
109
109
|
});
|
|
110
|
+
|
|
111
|
+
describe('and only the viewport height changes', () => {
|
|
112
|
+
beforeEach(async () => {
|
|
113
|
+
const viewport = page.viewport();
|
|
114
|
+
await setViewport(page, { width: viewport.width, height: viewport.height - 150 });
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('then the navigation menu stays displayed', async () => {
|
|
118
|
+
const isMenuNavVisible = await page.$eval('.ons-header-nav-menu', (el) => !el.classList.contains('ons-u-d-no'));
|
|
119
|
+
expect(isMenuNavVisible).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('then the menu button stays marked as expanded', async () => {
|
|
123
|
+
const menuButtonAriaExpanded = await page.$eval('.ons-btn--menu', (el) => el.getAttribute('aria-expanded'));
|
|
124
|
+
expect(menuButtonAriaExpanded).toBe('true');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
110
127
|
});
|
|
111
128
|
|
|
112
129
|
describe('when the menu button is not clicked', () => {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
'fullWidth': true
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
{% from "components/hero/_macro.njk" import onsHero %}
|
|
6
|
+
{{
|
|
7
|
+
onsHero({
|
|
8
|
+
"variants": 'grey',
|
|
9
|
+
"detailsColumns": '12',
|
|
10
|
+
"title": 'Lorem Ipsum',
|
|
11
|
+
"text": 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
|
|
12
|
+
"descriptionList": {
|
|
13
|
+
"termCol": "5",
|
|
14
|
+
"descriptionCol": "7",
|
|
15
|
+
"itemsList": [
|
|
16
|
+
{
|
|
17
|
+
"term": "Last updated:",
|
|
18
|
+
"descriptions": [
|
|
19
|
+
{
|
|
20
|
+
"description": "23 February 2024"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}}
|
|
@@ -90,15 +90,33 @@ export default class NavigationToggle {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
isHidden(el) {
|
|
93
|
-
|
|
93
|
+
if (!el) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const style = window.getComputedStyle(el);
|
|
98
|
+
if (style.display === 'none') {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// `offsetParent` can be `null` for reasons other than `display: none` (e.g. fixed positioning),
|
|
103
|
+
// so use layout rects as a more reliable proxy for visibility.
|
|
104
|
+
return el.getClientRects().length === 0;
|
|
94
105
|
}
|
|
95
106
|
|
|
96
|
-
setAria() {
|
|
107
|
+
setAria(viewportDetails = null) {
|
|
97
108
|
const isToggleHidden = this.isHidden(this.toggle);
|
|
98
109
|
this.toggle.setAttribute(attrDisabled, 'false');
|
|
99
110
|
|
|
100
111
|
this.searchToggleBtn?.setAttribute(attrDisabled, 'false');
|
|
101
112
|
|
|
113
|
+
// iOS Safari/Chrome can change viewport height during scroll when the browser chrome
|
|
114
|
+
// hides/shows, which can trigger resize events. If the user has the navigation open
|
|
115
|
+
// on a small screen, don't force-close it in response to these resizes.
|
|
116
|
+
if (viewportDetails && !isToggleHidden && this.navigation.getAttribute(attrHidden) === 'false') {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
if (!isToggleHidden) {
|
|
103
121
|
// close nav by default if toggle button is visible
|
|
104
122
|
this.closeNav();
|
|
@@ -259,6 +259,28 @@ describe('script: navigation', () => {
|
|
|
259
259
|
expect(hasClass).toBe(false);
|
|
260
260
|
});
|
|
261
261
|
});
|
|
262
|
+
|
|
263
|
+
describe('when the navigation is open and only the viewport height changes', () => {
|
|
264
|
+
beforeEach(async () => {
|
|
265
|
+
await page.focus(buttonEl);
|
|
266
|
+
await page.keyboard.press('Enter');
|
|
267
|
+
// Simulate iOS address bar show/hide which changes height during scroll
|
|
268
|
+
// without any meaningful layout/breakpoint change.
|
|
269
|
+
await setViewport(page, { width: 600, height: 900 });
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('keeps aria-hidden set as `false` on the navigation list', async () => {
|
|
273
|
+
const nav = await page.$(navEl);
|
|
274
|
+
const hasAriaAttribute = await nav.evaluate((node) => node.getAttribute('aria-hidden') === 'false');
|
|
275
|
+
expect(hasAriaAttribute).toBe(true);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('keeps aria-expanded set as `true` on the navigation toggle button', async () => {
|
|
279
|
+
const button = await page.$(buttonEl);
|
|
280
|
+
const ariaExpandedIsTrue = await button.evaluate((node) => node.getAttribute('aria-expanded') === 'true');
|
|
281
|
+
expect(ariaExpandedIsTrue).toBe(true);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
262
284
|
});
|
|
263
285
|
});
|
|
264
286
|
|
|
@@ -8,7 +8,16 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
{% endif %}
|
|
10
10
|
<div class="ons-grid__col ons-col-auto ons-u-flex-shrink">
|
|
11
|
-
<p class="ons-phase-banner__desc ons-u-fs-s ons-u-mb-no">
|
|
11
|
+
<p class="ons-phase-banner__desc ons-u-fs-s ons-u-mb-no">
|
|
12
|
+
{% if params.html %}
|
|
13
|
+
{{ params.html | safe }}
|
|
14
|
+
{% else %}
|
|
15
|
+
{{ params.text }}
|
|
16
|
+
{% if params.feedbackLink %}
|
|
17
|
+
{{ params.feedbackLink | safe }}
|
|
18
|
+
{% endif %}
|
|
19
|
+
{% endif %}
|
|
20
|
+
</p>
|
|
12
21
|
</div>
|
|
13
22
|
</div>
|
|
14
23
|
</div>
|
|
@@ -24,6 +24,33 @@ describe('macro: phase-banner', () => {
|
|
|
24
24
|
expect(htmlContent).toBe('Example content with a <a href="#">link</a>');
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
+
it('renders text content when `text` is provided', () => {
|
|
28
|
+
const $ = cheerio.load(
|
|
29
|
+
renderComponent('phase-banner', {
|
|
30
|
+
text: 'Example text content',
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const textContent = $('.ons-phase-banner__desc').text().trim();
|
|
35
|
+
expect(textContent).toBe('Example text content');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('renders feedbackLink when provided with text', () => {
|
|
39
|
+
const $ = cheerio.load(
|
|
40
|
+
renderComponent('phase-banner', {
|
|
41
|
+
text: 'Example text content',
|
|
42
|
+
feedbackLink: '<a href="#">give feedback</a>',
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const textContent = $('.ons-phase-banner__desc').text().replace(/\s+/g, ' ').trim();
|
|
47
|
+
expect(textContent).toBe('Example text content give feedback');
|
|
48
|
+
|
|
49
|
+
const link = $('.ons-phase-banner__desc a');
|
|
50
|
+
expect(link.length).toBe(1);
|
|
51
|
+
expect(link.text()).toBe('give feedback');
|
|
52
|
+
});
|
|
53
|
+
|
|
27
54
|
it('has the "Beta" badge by default', () => {
|
|
28
55
|
const $ = cheerio.load(renderComponent('phase-banner', EXAMPLE_PHASE_BANNER_MINIMAL));
|
|
29
56
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{% from "components/phase-banner/_macro.njk" import onsPhaseBanner %}
|
|
2
|
+
{% from "components/external-link/_macro.njk" import onsExternalLink %}
|
|
3
|
+
|
|
4
|
+
{% set feedbackLink %}
|
|
5
|
+
{{
|
|
6
|
+
onsExternalLink({
|
|
7
|
+
"url": "#0",
|
|
8
|
+
"text": "give feedback"
|
|
9
|
+
})
|
|
10
|
+
}}
|
|
11
|
+
{% endset %}
|
|
12
|
+
|
|
13
|
+
{{
|
|
14
|
+
onsPhaseBanner({
|
|
15
|
+
"text": "This is a new service. To help us improve it,",
|
|
16
|
+
"feedbackLink": feedbackLink
|
|
17
|
+
})
|
|
18
|
+
}}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
{% for th in headerCols.ths %}
|
|
36
36
|
<th
|
|
37
37
|
scope="col"
|
|
38
|
-
class="ons-table__header{{ ' ' + th.thClasses if th.thClasses else '' }}{{ ' ons-table__header--numeric' if th.numeric }}"
|
|
38
|
+
class="ons-table__header ons-table__header--{{ th.valign | default('top') }}{{ ' ' + th.thClasses if th.thClasses else '' }}{{ ' ons-table__header--numeric' if th.numeric }}"
|
|
39
39
|
{% if th.colspan %}colspan="{{ th.colspan }}"{% endif %}
|
|
40
40
|
{% if th.rowspan %}rowspan="{{ th.rowspan }}"{% endif %}
|
|
41
41
|
{% if 'sortable' in variants %}aria-sort="{{ th.ariaSort | default('none') }}"{% endif %}
|
|
@@ -73,7 +73,8 @@
|
|
|
73
73
|
{% set isFirstRow = loop.index == 0 and td.rowspan %}
|
|
74
74
|
{% set rowSpan = isFirstRow and loop.index0 == rowspanCount %}
|
|
75
75
|
{{ openingTag | safe }}
|
|
76
|
-
class="ons-table__cell
|
|
76
|
+
class="ons-table__cell
|
|
77
|
+
ons-table__cell--{{ td.valign | default('top') }}{{ ' ' + td.tdClasses if td.tdClasses else '' }}{{ ' ons-table__cell--numeric' if td.numeric }}"
|
|
77
78
|
{% if td.id %}id="{{ td.id }}"{% endif %}
|
|
78
79
|
{% if td.data %}{{ ' ' }}data-th="{{ td.data }}"{% endif %}
|
|
79
80
|
{% if td.colspan %}colspan="{{ td.colspan }}"{% endif %}
|
|
@@ -107,7 +108,9 @@
|
|
|
107
108
|
<tfoot class="ons-table__foot">
|
|
108
109
|
<tr class="ons-table__row">
|
|
109
110
|
{% for tfootCell in params.tfoot %}
|
|
110
|
-
<td class="ons-table__cell ons-
|
|
111
|
+
<td class="ons-table__cell ons-table__cell--{{ tfootCell.valign | default('top') }} ons-u-fs-s">
|
|
112
|
+
{{ tfootCell.value }}
|
|
113
|
+
</td>
|
|
111
114
|
{% endfor %}
|
|
112
115
|
</tr>
|
|
113
116
|
</tfoot>
|
|
@@ -90,6 +90,51 @@ describe('macro: table', () => {
|
|
|
90
90
|
expect($('.ons-table-scrollable__content').attr('aria-label')).toBe('Example table caption. Special table');
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
+
describe('Vertical Alignment', () => {
|
|
94
|
+
it('adds "ons-table__header--middle" class to column header when valign is set', () => {
|
|
95
|
+
const $ = cheerio.load(
|
|
96
|
+
renderComponent('table', {
|
|
97
|
+
...EXAMPLE_TABLE,
|
|
98
|
+
ths: [
|
|
99
|
+
{
|
|
100
|
+
value: 'Column 1',
|
|
101
|
+
valign: 'middle',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect($('.ons-table__header').hasClass('ons-table__header--middle')).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('adds "ons-table__header--top" class to column header when valign is not set', () => {
|
|
111
|
+
const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
|
|
112
|
+
|
|
113
|
+
expect($('.ons-table__header').hasClass('ons-table__header--top')).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('adds "ons-table__cell--middle" class to row when valign is middle', () => {
|
|
117
|
+
const $ = cheerio.load(
|
|
118
|
+
renderComponent('table', {
|
|
119
|
+
...EXAMPLE_TABLE,
|
|
120
|
+
trs: [
|
|
121
|
+
{
|
|
122
|
+
tds: [{ value: 'Row 1 Cell 1', valign: 'middle' }],
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect($('.ons-table__cell').hasClass('ons-table__cell--middle')).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('adds "ons-table__cell--top" class to row when valign is not set', () => {
|
|
132
|
+
const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
|
|
133
|
+
|
|
134
|
+
expect($('.ons-table__cell').hasClass('ons-table__cell--top')).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
93
138
|
describe('header row', () => {
|
|
94
139
|
it('renders header cells with expected text', () => {
|
|
95
140
|
const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
|
|
@@ -529,6 +574,19 @@ describe('macro: table', () => {
|
|
|
529
574
|
const footerCellValues = mapAll($('.ons-table__foot .ons-table__cell'), (node) => node.text().trim());
|
|
530
575
|
expect(footerCellValues).toEqual(['Footer Cell 1', 'Footer Cell 2', 'Footer Cell 3']);
|
|
531
576
|
});
|
|
577
|
+
it('adds "ons-table__cell--middle" class to row when valign is middle', () => {
|
|
578
|
+
const $ = cheerio.load(
|
|
579
|
+
renderComponent('table', {
|
|
580
|
+
...EXAMPLE_TABLE,
|
|
581
|
+
tfoot: [
|
|
582
|
+
{ value: 'Footer Cell 1', valign: 'middle' },
|
|
583
|
+
{ value: 'Footer Cell 2', valign: 'middle' },
|
|
584
|
+
],
|
|
585
|
+
}),
|
|
586
|
+
);
|
|
587
|
+
|
|
588
|
+
expect($('.ons-table__cell').hasClass('ons-table__cell--middle')).toBe(true);
|
|
589
|
+
});
|
|
532
590
|
});
|
|
533
591
|
|
|
534
592
|
describe('sortable variant', () => {
|
|
@@ -26,10 +26,18 @@
|
|
|
26
26
|
overflow: hidden;
|
|
27
27
|
padding: 0.5rem 0 0.5rem 1rem;
|
|
28
28
|
text-align: left;
|
|
29
|
-
vertical-align: top;
|
|
30
29
|
&--numeric {
|
|
31
30
|
text-align: right;
|
|
32
31
|
}
|
|
32
|
+
&--top {
|
|
33
|
+
vertical-align: top;
|
|
34
|
+
}
|
|
35
|
+
&--bottom {
|
|
36
|
+
vertical-align: bottom;
|
|
37
|
+
}
|
|
38
|
+
&--center {
|
|
39
|
+
vertical-align: middle;
|
|
40
|
+
}
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
&--has-rowspan {
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
{% from "components/table/_macro.njk" import onsTable %}
|
|
2
|
+
{{
|
|
3
|
+
onsTable({
|
|
4
|
+
"caption": "Table with cells merged, multiple row headers and column headers",
|
|
5
|
+
"id": "basic-table",
|
|
6
|
+
"ths": [
|
|
7
|
+
{
|
|
8
|
+
"value": "Trade Category"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"value": "Metrics"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"value": "Exports"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"value": "Imports"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"value": "Balance"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
],
|
|
24
|
+
"trs": [
|
|
25
|
+
{
|
|
26
|
+
"tds": [
|
|
27
|
+
{
|
|
28
|
+
"heading": true,
|
|
29
|
+
"value": "Total trade in goods: December 2024 vs November 2024",
|
|
30
|
+
"rowspan":3,
|
|
31
|
+
"valign": "center"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"heading": true,
|
|
35
|
+
"value": "Value (£bn)"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"value": "28.8"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"value": "45.7"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"value": "-16.9"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"tds": [
|
|
50
|
+
{
|
|
51
|
+
"heading": true,
|
|
52
|
+
"value": "Change (£bn)"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"value": "0.0"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"value": "-1.2"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"value": "1.2"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"tds": [
|
|
67
|
+
{
|
|
68
|
+
"heading": true,
|
|
69
|
+
"value": "%Change"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"value": "0.0"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"value": "2.6"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"value": ""
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"tds": [
|
|
84
|
+
{
|
|
85
|
+
"heading": true,
|
|
86
|
+
"value": "EU: December 2024 vs November 2024",
|
|
87
|
+
"rowspan": 3,
|
|
88
|
+
"valign": "center"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"value": "Value (£bn)",
|
|
92
|
+
"heading": true
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"value": "13.6"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"value": "24.9"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"value": "-11.3"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"tds": [
|
|
107
|
+
{
|
|
108
|
+
"value": "Change (£bn)",
|
|
109
|
+
"heading": true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"value": "-0.5"
|
|
113
|
+
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"value": "-0.8"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"value": "0.3"
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"tds": [
|
|
125
|
+
{
|
|
126
|
+
"heading": true,
|
|
127
|
+
"value": "%Change"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"value": "3.5"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"value": "-1.8"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"value": ""
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
})
|
|
142
|
+
}}
|