@ons/design-system 45.2.1 → 46.1.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.
@@ -74,81 +74,68 @@ export default class AutosuggestAddress {
74
74
  this.checkAPIStatus();
75
75
  }
76
76
 
77
- checkAPIStatus() {
77
+ async checkAPIStatus() {
78
78
  this.fetch = abortableFetch(this.lookupURL + 'CF142&limit=10', {
79
79
  method: 'GET',
80
80
  headers: this.setAuthorization(this.authorizationToken),
81
81
  });
82
- this.fetch
83
- .send()
84
- .then(async response => {
85
- const status = (await response.json()).status.code;
86
- if (status > 400) {
87
- if (this.isEditable) {
88
- this.handleAPIError();
89
- } else {
90
- this.autosuggest.handleNoResults(status);
91
- }
92
- }
93
- })
94
- .catch(error => {
95
- console.log(error);
82
+ try {
83
+ const response = await this.fetch.send();
84
+ const status = (await response.json()).status.code;
85
+ if (status > 400) {
96
86
  if (this.isEditable) {
97
87
  this.handleAPIError();
98
88
  } else {
99
89
  this.autosuggest.handleNoResults(status);
100
90
  }
101
- });
91
+ }
92
+ } catch (error) {
93
+ console.log(error);
94
+ if (this.isEditable) {
95
+ this.handleAPIError();
96
+ } else {
97
+ this.autosuggest.handleNoResults(status);
98
+ }
99
+ }
102
100
  }
103
101
 
104
- suggestAddresses(query, [], grouped) {
105
- return new Promise((resolve, reject) => {
106
- if (this.fetch && this.fetch.status !== 'DONE') {
107
- this.fetch.abort();
108
- }
102
+ async suggestAddresses(query, [], grouped) {
103
+ if (this.fetch && this.fetch.status !== 'DONE') {
104
+ this.fetch.abort();
105
+ }
109
106
 
110
- this.reject = reject;
111
- this.findAddress(query, grouped)
112
- .then(resolve)
113
- .catch(reject);
114
- });
107
+ return await this.findAddress(query, grouped);
115
108
  }
116
109
 
117
- findAddress(text, grouped) {
118
- return new Promise((resolve, reject) => {
119
- let queryURL, fullQueryURL;
110
+ async findAddress(text, grouped) {
111
+ let queryURL, fullQueryURL;
120
112
 
121
- if (this.manualQueryParams) {
122
- const manualQueryParams = this.container.getAttribute('data-query-params');
123
- fullQueryURL = this.lookupURL + text + manualQueryParams;
124
- } else {
125
- const fullPostcodeQuery = this.testFullPostcodeQuery(text);
126
- let limit = fullPostcodeQuery ? 100 : 10;
113
+ if (this.manualQueryParams) {
114
+ const manualQueryParams = this.container.getAttribute('data-query-params');
115
+ fullQueryURL = this.lookupURL + text + manualQueryParams;
116
+ } else {
117
+ const fullPostcodeQuery = this.testFullPostcodeQuery(text);
118
+ let limit = fullPostcodeQuery ? 100 : 10;
127
119
 
128
- queryURL = grouped ? this.lookupGroupURL + this.groupQuery : this.lookupURL + text + '&limit=' + limit;
120
+ queryURL = grouped ? this.lookupGroupURL + this.groupQuery : this.lookupURL + text + '&limit=' + limit;
129
121
 
130
- fullQueryURL = this.generateURLParams(queryURL);
131
- if (fullPostcodeQuery && grouped !== false) {
132
- fullQueryURL = fullQueryURL + '&groupfullpostcodes=combo';
133
- }
122
+ fullQueryURL = this.generateURLParams(queryURL);
123
+ if (fullPostcodeQuery && grouped !== false) {
124
+ fullQueryURL = fullQueryURL + '&groupfullpostcodes=combo';
134
125
  }
126
+ }
135
127
 
136
- this.fetch = abortableFetch(fullQueryURL, {
137
- method: 'GET',
138
- headers: this.setAuthorization(this.authorizationToken),
139
- });
140
- this.fetch
141
- .send()
142
- .then(async data => {
143
- const response = await data.json();
144
- const status = response.status.code;
145
- const addresses = response.response;
146
- const limit = response.response.limit;
147
- const results = await this.mapFindResults(addresses, limit, status);
148
- resolve(results);
149
- })
150
- .catch(reject);
128
+ this.fetch = abortableFetch(fullQueryURL, {
129
+ method: 'GET',
130
+ headers: this.setAuthorization(this.authorizationToken),
151
131
  });
132
+ const data = await this.fetch.send();
133
+ const response = await data.json();
134
+ const status = response.status.code;
135
+ const addresses = response.response;
136
+ const limit = response.response.limit;
137
+ const results = await this.mapFindResults(addresses, limit, status);
138
+ return results;
152
139
  }
153
140
 
154
141
  async mapFindResults(results, limit, status) {
@@ -262,75 +249,66 @@ export default class AutosuggestAddress {
262
249
  }
263
250
  }
264
251
 
265
- retrieveAddress(id, type = null) {
266
- return new Promise((resolve, reject) => {
267
- let retrieveUrl = this.retrieveURL + id;
268
-
269
- const fullUPRNURL = this.generateURLParams(retrieveUrl, id, type);
252
+ async retrieveAddress(id, type = null) {
253
+ let retrieveUrl = this.retrieveURL + id;
270
254
 
271
- this.fetch = abortableFetch(fullUPRNURL, {
272
- method: 'GET',
273
- headers: this.setAuthorization(this.authorizationToken),
274
- });
255
+ const fullUPRNURL = this.generateURLParams(retrieveUrl, id, type);
275
256
 
276
- this.fetch
277
- .send()
278
- .then(async response => {
279
- const data = await response.json();
280
- resolve(data);
281
- })
282
- .catch(reject);
257
+ this.fetch = abortableFetch(fullUPRNURL, {
258
+ method: 'GET',
259
+ headers: this.setAuthorization(this.authorizationToken),
283
260
  });
261
+
262
+ const response = await this.fetch.send();
263
+ const data = await response.json();
264
+ return data;
284
265
  }
285
266
 
286
- onAddressSelect(selectedResult) {
287
- return new Promise((resolve, reject) => {
288
- if (selectedResult.uprn) {
289
- this.retrieveAddress(selectedResult.uprn, selectedResult.type)
290
- .then(data => {
291
- if (this.isEditable) {
292
- if (data.status.code >= 403) {
293
- this.autosuggest.handleNoResults(403);
294
- } else {
295
- this.addressSetter.setAddress(this.createAddressLines(data, resolve));
296
- this.addressSelected = true;
297
- }
298
- } else {
299
- this.selectedAddressValue = selectedResult.displayText;
300
- this.autosuggest.input.value = selectedResult.displayText;
301
- this.uprn.value = selectedResult.uprn;
302
- this.addressSelected = true;
303
- }
304
- })
305
- .catch(error => {
306
- console.log(error);
307
- if (this.isEditable) {
308
- this.handleAPIError();
309
- } else {
310
- this.autosuggest.handleNoResults(403);
311
- }
312
- reject();
313
- });
314
- } else if (selectedResult.postcode) {
315
- this.autosuggest.input.value =
316
- selectedResult.streetName +
317
- ', ' +
318
- (selectedResult.townName === selectedResult.postTown
319
- ? selectedResult.postTown
320
- : selectedResult.townName + ', ' + selectedResult.postTown) +
321
- ', ' +
322
- selectedResult.postcode;
323
- this.autosuggest.input.focus();
324
- this.groupQuery =
325
- 'postcode=' + selectedResult.postcode + '&streetname=' + selectedResult.streetName + '&townname=' + selectedResult.townName;
326
- this.autosuggest.handleChange(true);
267
+ async onAddressSelect(selectedResult) {
268
+ if (selectedResult.uprn) {
269
+ try {
270
+ const data = await this.retrieveAddress(selectedResult.uprn, selectedResult.type);
271
+ if (this.isEditable) {
272
+ if (data.status.code >= 403) {
273
+ this.autosuggest.handleNoResults(403);
274
+ } else {
275
+ this.addressSetter.setAddress(this.createAddressLines(data));
276
+ this.addressSelected = true;
277
+ }
278
+ } else {
279
+ this.selectedAddressValue = selectedResult.displayText;
280
+ this.autosuggest.input.value = selectedResult.displayText;
281
+ this.uprn.value = selectedResult.uprn;
282
+ this.addressSelected = true;
283
+ }
284
+ } catch (error) {
285
+ console.log(error);
286
+ if (this.isEditable) {
287
+ this.handleAPIError();
288
+ } else {
289
+ this.autosuggest.handleNoResults(403);
290
+ }
291
+ throw error;
327
292
  }
328
- });
293
+ } else if (selectedResult.postcode) {
294
+ this.autosuggest.input.value =
295
+ selectedResult.streetName +
296
+ ', ' +
297
+ (selectedResult.townName === selectedResult.postTown
298
+ ? selectedResult.postTown
299
+ : selectedResult.townName + ', ' + selectedResult.postTown) +
300
+ ', ' +
301
+ selectedResult.postcode;
302
+ this.autosuggest.input.focus();
303
+ this.groupQuery =
304
+ 'postcode=' + selectedResult.postcode + '&streetname=' + selectedResult.streetName + '&townname=' + selectedResult.townName;
305
+ this.autosuggest.handleChange(true);
306
+ }
329
307
  }
330
308
 
331
- createAddressLines(data, resolve) {
309
+ createAddressLines(data) {
332
310
  const values = data.response.address;
333
- const addressLines = {
311
+ return {
334
312
  addressLine1: values.addressLine1,
335
313
  addressLine2: values.addressLine2,
336
314
  addressLine3: values.addressLine3,
@@ -338,9 +316,6 @@ export default class AutosuggestAddress {
338
316
  postcode: values.postcode,
339
317
  uprn: values.uprn,
340
318
  };
341
- resolve();
342
-
343
- return addressLines;
344
319
  }
345
320
 
346
321
  generateURLParams(baseURL, uprn, type) {
@@ -14,19 +14,11 @@ export default class Autosuggest {
14
14
  });
15
15
  }
16
16
 
17
- onSelect(result) {
18
- return new Promise(resolve => {
19
- this.autosuggest.input.value = result.displayText;
20
-
21
- resolve();
22
- });
17
+ async onSelect(result) {
18
+ this.autosuggest.input.value = result.displayText;
23
19
  }
24
20
 
25
- onUnsetResult() {
26
- return new Promise(resolve => {
27
- resolve();
28
- });
29
- }
21
+ async onUnsetResult() {}
30
22
 
31
23
  onError(error) {
32
24
  console.error(error);
@@ -120,17 +120,10 @@ export default class AutosuggestUI {
120
120
  this.bindEventListeners();
121
121
  }
122
122
 
123
- fetchData() {
123
+ async fetchData() {
124
124
  this.fetch = abortableFetch(this.autosuggestData);
125
- return new Promise((resolve, reject) => {
126
- this.fetch
127
- .send()
128
- .then(async response => {
129
- this.data = await response.json();
130
- resolve(this.data);
131
- })
132
- .catch(reject);
133
- });
125
+ const response = await this.fetch.send();
126
+ this.data = await response.json();
134
127
  }
135
128
 
136
129
  bindEventListeners() {
@@ -42,4 +42,10 @@
42
42
  min-height: 1.5rem;
43
43
  }
44
44
  }
45
+
46
+ &--rows {
47
+ li {
48
+ margin-bottom: 0.5rem !important;
49
+ }
50
+ }
45
51
  }
@@ -163,6 +163,7 @@
163
163
  <div class="ons-grid__col">
164
164
  {{
165
165
  onsList({
166
+ "classes": "ons-footer--rows",
166
167
  "variants": ["bare", "inline"],
167
168
  "itemsList": row.itemsList
168
169
  })
@@ -227,7 +228,7 @@
227
228
  <div class="ons-grid__col">
228
229
  {{
229
230
  onsList({
230
- "classes": 'ons-u-mb-m',
231
+ "classes": 'ons-u-mb-m ons-footer--rows',
231
232
  "variants": ['bare', 'inline'],
232
233
  "itemsList": legal.itemsList
233
234
  })
@@ -13,23 +13,18 @@
13
13
  {% set otherClasses = '' %}
14
14
  {% endif %}
15
15
 
16
- {% if params.element is defined and params.element %}
16
+ {% if params.element is defined and params.element and listLength > 1 %}
17
17
  {% set listEl = params.element | lower %}
18
+ {% elif (params.element is defined and params.element == 'ol') and listLength < 2 %}
19
+ {% set listEl = 'p' %}
18
20
  {% else %}
19
21
  {% set listEl = 'ul' %}
20
22
  {% endif %}
21
-
22
- {% if (params.element is defined and params.element == 'ol') and listLength < 2 %}
23
- <p {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}{% if params.classes is defined and params.classes %} class="{{ params.classes -}}"{% endif %}>
24
- {%- for item in params.itemsList -%}
25
- {{ item.text }}
26
- {%- endfor -%}
27
- </p>
28
- {% else %}
29
- <{{listEl}} {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}class="{% if listLength > 1 %}ons-list{% endif %}{% if params.classes is defined and params.classes %} {{ params.classes -}}{% endif %}{% if params.variants is defined and params.variants %}{% if params.variants is not string %}{% for variant in params.variants %} ons-list--{{ variant }}{% endfor %}{% else %} ons-list--{{ params.variants }}{% endif %}{% endif %}{% if otherClasses %} {{ otherClasses -}}{% endif %}">
23
+ <{{listEl}} {% if params.id is defined and params.id %}id="{{ params.id }}"{% endif %}class="{% if listLength > 1 or listEl == 'ul' %}ons-list{% else %}ons-list--p{% endif %}{% if params.classes is defined and params.classes %} {{ params.classes -}}{% endif %}{% if params.variants is defined and params.variants %}{% if params.variants is not string %}{% for variant in params.variants %} ons-list--{{ variant }}{% endfor %}{% else %} ons-list--{{ params.variants }}{% endif %}{% endif %}{% if otherClasses %} {{ otherClasses -}}{% endif %}">
30
24
  {%- for item in (params.itemsList if params.itemsList is iterable else params.itemsList.items()) -%}
25
+ {% if listLength > 1 or listEl == 'ul' %}
31
26
  <li class="ons-list__item{% if item.listClasses is defined and item.listClasses %} {{ item.listClasses }}{% endif %}"{% if item.current is defined and item.current %} aria-current="true"{% endif %}>
32
-
27
+ {% endif %}
33
28
  {% set itemText = item.text %}
34
29
 
35
30
  {% if params.itemsList[0] is defined and item.iconType is defined and item.iconType %}
@@ -94,8 +89,9 @@
94
89
  }}
95
90
  {%- endif -%} </span>
96
91
  {%- endif -%}
92
+ {% if listLength > 1 or listEl == 'ul' %}
97
93
  </li>
94
+ {% endif %}
98
95
  {%- endfor -%}
99
96
  </{{listEl}}>
100
- {% endif %}
101
97
  {% endmacro %}
@@ -1,4 +1,4 @@
1
- {% macro onsModal(params) %}
1
+ {% macro onsModal(params) %}
2
2
  {% set modalID = params.id | default('dialog') %}
3
3
  <dialog class="ons-modal ons-js-modal {{ params.classes }}"
4
4
  id="{{ modalID }}"
@@ -29,6 +29,8 @@
29
29
  {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
30
30
  <div class="{{containerClass}}">
31
31
  <div class="ons-container">
32
+ {% elif params.type is defined and params.type == "warn" %}
33
+ <div class="ons-container">
32
34
  {% endif %}
33
35
 
34
36
  <div {% if params is defined and params and params.type == 'error' and params.title is defined and params.title %}aria-labelledby="error-summary-title" role="alert" tabindex="-1" {% if params.dsExample != true %}autofocus="autofocus" {% endif %}{% endif %}class="ons-panel{{ typeClass }}{{ iconClass }}{{ noTitleClass }}{{ spaciousClass }}{{ classes }}"{% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}{% if params is defined and params and params.id is defined and params.id %} id="{{params.id}}"{% endif %}>
@@ -86,7 +88,7 @@
86
88
  {% endif %}
87
89
  {% endif %}
88
90
 
89
- <div class="ons-panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} ons-svg-icon-margin--{{ params.iconSize }}{% endif %}" {% if params is defined and params and params.attributes is defined and params.attributes %}{% for attribute, value in (params.attributes.items() if params is defined and params and params.attributes is mapping and params.attributes.items is defined and params.attributes.items else params.attributes) %}{{attribute}}="{{value}}" {% endfor %}{% endif %}>{{ (params.body if params else "") | safe }}
91
+ <div class="ons-panel__body{% if params is defined and params and params.iconSize is defined and params.iconSize %} ons-svg-icon-margin--{{ params.iconSize }}{% endif %}">{{ (params.body if params else "") | safe }}
90
92
  {{ caller() if caller }}
91
93
  </div>
92
94
 
@@ -95,6 +97,8 @@
95
97
  {% if params is defined and params and params.type == "warn-branded" or params.type == "announcement" %}
96
98
  </div>
97
99
  </div>
100
+ {% elif params.type is defined and params.type == "warn" %}
101
+ </div>
98
102
  {% endif %}
99
103
 
100
104
  {% endmacro %}
@@ -47,6 +47,10 @@
47
47
  padding: 0.75rem 1rem;
48
48
  }
49
49
 
50
+ &__timer {
51
+ white-space: nowrap;
52
+ }
53
+
50
54
  &__title {
51
55
  margin: 0;
52
56
  }
@@ -1,5 +1,5 @@
1
1
  {% from "components/modal/_macro.njk" import onsModal %}
2
- {% macro onsTimeoutModal(params) %}
2
+ {% macro onsTimeoutModal(params) %}
3
3
  {% call onsModal({
4
4
  "title": params.title,
5
5
  "btnText": params.btnText,
@@ -10,11 +10,12 @@
10
10
  "data-show-modal-time": params.showModalTimeInSeconds,
11
11
  "data-server-session-expiry-endpoint": params.serverSessionExpiryEndpoint,
12
12
  "data-countdown-text": params.countdownText,
13
- "data-redirecting-text": params.redirectingText,
13
+ "data-countdown-expired-text": params.countdownExpiredText,
14
14
  "data-minutes-text-singular": params.minutesTextSingular,
15
15
  "data-minutes-text-plural": params.minutesTextPlural,
16
16
  "data-seconds-text-singular": params.secondsTextSingular,
17
17
  "data-seconds-text-plural": params.secondsTextPlural,
18
+ "data-full-stop": params.endWithFullStop,
18
19
  "aria-describedby": "timeout-time-remaining"
19
20
  }
20
21
  })
@@ -4,12 +4,12 @@ async function modals() {
4
4
  const timeouts = [...document.querySelectorAll('.ons-js-timeout-modal')];
5
5
 
6
6
  if (timeouts.length) {
7
- const Timeout = (await import('./timeout')).default;
7
+ const TimeoutModal = (await import('./timeout-modal')).default;
8
8
 
9
9
  timeouts.forEach(context => {
10
10
  let url = context.getAttribute('data-server-session-expiry-endpoint');
11
11
  let time = context.getAttribute('data-server-session-expires-at');
12
- new Timeout(context, url, time);
12
+ new TimeoutModal(context, url, time);
13
13
  });
14
14
  }
15
15
  }
@@ -0,0 +1,62 @@
1
+ import Modal from '../modal/modal';
2
+ import Timeout from '../../js/timeout';
3
+
4
+ export default class TimeoutModal {
5
+ constructor(context, sessionExpiryEndpoint, initialExpiryTime) {
6
+ this.context = context;
7
+ this.sessionExpiryEndpoint = sessionExpiryEndpoint;
8
+ this.initialExpiryTime = initialExpiryTime;
9
+ this.continueButton = context.querySelector('.ons-js-modal-btn');
10
+ this.modalVisibleInMilliseconds = context.getAttribute('data-show-modal-time') * 1000;
11
+
12
+ // Create modal instance
13
+ this.modal = new Modal(this.context);
14
+
15
+ // Create timeout instance
16
+ this.timeout = new Timeout(this.context, this.sessionExpiryEndpoint, this.initialExpiryTime, true);
17
+
18
+ this.bindEventListeners();
19
+ }
20
+
21
+ bindEventListeners() {
22
+ window.onload = this.startTimeout();
23
+ window.addEventListener('keydown', this.escToClose.bind(this));
24
+ this.continueButton.addEventListener('click', this.closeModalAndRestartTimeout.bind(this));
25
+ }
26
+
27
+ startTimeout() {
28
+ clearTimeout(this.showModalTimeout);
29
+ if (this.initialExpiryTime) {
30
+ this.expiryTimeInMilliseconds = this.timeout.convertTimeToMilliSeconds(this.initialExpiryTime);
31
+ } else {
32
+ // For demo purposes
33
+ this.expiryTimeInMilliseconds = 60000;
34
+ }
35
+ this.showModalTimeout = setTimeout(
36
+ this.openModalAndStartCountdown.bind(this),
37
+ this.expiryTimeInMilliseconds - this.modalVisibleInMilliseconds,
38
+ );
39
+ }
40
+
41
+ async openModalAndStartCountdown() {
42
+ const modalWillOpen = await this.timeout.hasExpiryTimeResetInAnotherTab();
43
+ if (modalWillOpen && !this.modal.isDialogOpen()) {
44
+ this.modal.openDialog();
45
+ this.timeout.startUiCountdown();
46
+ }
47
+ }
48
+
49
+ closeModalAndRestartTimeout() {
50
+ if (this.modal.isDialogOpen()) {
51
+ this.modal.closeDialog();
52
+ }
53
+ this.timeout.restartTimeout();
54
+ this.startTimeout();
55
+ }
56
+
57
+ escToClose(event) {
58
+ if (this.modal.isDialogOpen() && event.keyCode === 27) {
59
+ this.closeModalAndRestartTimeout();
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,26 @@
1
+ {% from "components/panel/_macro.njk" import onsPanel %}
2
+ {% macro onsTimeoutPanel(params) %}
3
+ {% call onsPanel({
4
+ "id": params.id,
5
+ "classes": "ons-js-panel-with-countdown",
6
+ "type": "warn",
7
+ "attributes": {
8
+ "data-redirect-url": params.redirectUrl,
9
+ "data-server-session-expires-at": params.sessionExpiresAt,
10
+ "data-server-session-expiry-endpoint": params.serverSessionExpiryEndpoint,
11
+ "data-countdown-text": params.countdownText,
12
+ "data-countdown-expired-text": params.countdownExpiredText,
13
+ "data-minutes-text-singular": params.minutesTextSingular,
14
+ "data-minutes-text-plural": params.minutesTextPlural,
15
+ "data-seconds-text-singular": params.secondsTextSingular,
16
+ "data-seconds-text-plural": params.secondsTextPlural,
17
+ "data-full-stop": params.endWithFullStop,
18
+ "aria-describedby": "timeout-time-remaining"
19
+ }
20
+ })
21
+ %}
22
+ <noscript><p class="ons-js-nojs-text">{{ params.nojsText }}</p></noscript>
23
+ <p class="ons-js-timeout-timer" aria-hidden="true" aria-relevant="additions"></p>
24
+ <p class="ons-js-timeout-timer-acc ons-u-vh" role="status" id="timeout-time-remaining"></p>
25
+ {% endcall %}
26
+ {% endmacro %}
@@ -0,0 +1,17 @@
1
+ import domready from '../../js/domready';
2
+
3
+ async function timeoutPanels() {
4
+ const panels = [...document.querySelectorAll('.ons-js-panel-with-countdown')];
5
+
6
+ if (panels.length) {
7
+ const Timeout = (await import('../../js/timeout')).default;
8
+
9
+ panels.forEach(context => {
10
+ let url = context.getAttribute('data-server-session-expiry-endpoint');
11
+ let time = context.getAttribute('data-server-session-expires-at');
12
+ new Timeout(context, url, time, false, true);
13
+ });
14
+ }
15
+ }
16
+
17
+ domready(timeoutPanels);