govuk_publishing_components 43.4.0 → 43.5.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/views/govuk_publishing_components/components/_radio.html.erb +2 -0
  3. data/app/views/govuk_publishing_components/components/docs/inverse_header.yml +2 -30
  4. data/app/views/govuk_publishing_components/components/docs/radio.yml +15 -0
  5. data/lib/govuk_publishing_components/version.rb +1 -1
  6. data/node_modules/accessible-autocomplete/CHANGELOG.md +398 -0
  7. data/node_modules/accessible-autocomplete/CODEOWNERS +2 -0
  8. data/node_modules/accessible-autocomplete/CONTRIBUTING.md +161 -0
  9. data/node_modules/accessible-autocomplete/LICENSE.txt +20 -0
  10. data/node_modules/accessible-autocomplete/Procfile +1 -0
  11. data/node_modules/accessible-autocomplete/README.md +490 -0
  12. data/node_modules/accessible-autocomplete/accessibility-criteria.md +43 -0
  13. data/node_modules/accessible-autocomplete/app.json +15 -0
  14. data/node_modules/accessible-autocomplete/babel.config.js +29 -0
  15. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.css +3 -0
  16. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.css.map +1 -0
  17. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.js +2 -0
  18. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.js.map +1 -0
  19. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.preact.min.js +2 -0
  20. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.preact.min.js.map +1 -0
  21. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.react.min.js +2 -0
  22. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.react.min.js.map +1 -0
  23. data/node_modules/accessible-autocomplete/examples/ajax-source.html +300 -0
  24. data/node_modules/accessible-autocomplete/examples/form-single.html +381 -0
  25. data/node_modules/accessible-autocomplete/examples/form.html +673 -0
  26. data/node_modules/accessible-autocomplete/examples/index.html +693 -0
  27. data/node_modules/accessible-autocomplete/examples/preact/index.html +346 -0
  28. data/node_modules/accessible-autocomplete/examples/react/index.html +347 -0
  29. data/node_modules/accessible-autocomplete/examples/suggestions.json +258 -0
  30. data/node_modules/accessible-autocomplete/package.json +93 -0
  31. data/node_modules/accessible-autocomplete/postcss.config.js +16 -0
  32. data/node_modules/accessible-autocomplete/preact.js +1 -0
  33. data/node_modules/accessible-autocomplete/react.js +1 -0
  34. data/node_modules/accessible-autocomplete/scripts/check-staged.mjs +16 -0
  35. data/node_modules/accessible-autocomplete/src/autocomplete.css +167 -0
  36. data/node_modules/accessible-autocomplete/src/autocomplete.js +610 -0
  37. data/node_modules/accessible-autocomplete/src/dropdown-arrow-down.js +11 -0
  38. data/node_modules/accessible-autocomplete/src/status.js +125 -0
  39. data/node_modules/accessible-autocomplete/src/wrapper.js +60 -0
  40. data/node_modules/accessible-autocomplete/test/functional/dropdown-arrow-down.js +46 -0
  41. data/node_modules/accessible-autocomplete/test/functional/index.js +809 -0
  42. data/node_modules/accessible-autocomplete/test/functional/wrapper.js +339 -0
  43. data/node_modules/accessible-autocomplete/test/integration/index.js +309 -0
  44. data/node_modules/accessible-autocomplete/test/karma.config.js +46 -0
  45. data/node_modules/accessible-autocomplete/test/wdio.config.js +123 -0
  46. data/node_modules/accessible-autocomplete/webpack.config.mjs +244 -0
  47. metadata +57 -2
@@ -0,0 +1,125 @@
1
+ import { createElement, Component } from 'preact' /** @jsx createElement */
2
+
3
+ const debounce = function (func, wait, immediate) {
4
+ let timeout
5
+ return function () {
6
+ const context = this
7
+ const args = arguments
8
+ const later = function () {
9
+ timeout = null
10
+ if (!immediate) func.apply(context, args)
11
+ }
12
+ const callNow = immediate && !timeout
13
+ clearTimeout(timeout)
14
+ timeout = setTimeout(later, wait)
15
+ if (callNow) func.apply(context, args)
16
+ }
17
+ }
18
+ const statusDebounceMillis = 1400
19
+
20
+ export default class Status extends Component {
21
+ static defaultProps = {
22
+ tQueryTooShort: (minQueryLength) => `Type in ${minQueryLength} or more characters for results`,
23
+ tNoResults: () => 'No search results',
24
+ tSelectedOption: (selectedOption, length, index) => `${selectedOption} ${index + 1} of ${length} is highlighted`,
25
+ tResults: (length, contentSelectedOption) => {
26
+ const words = {
27
+ result: (length === 1) ? 'result' : 'results',
28
+ is: (length === 1) ? 'is' : 'are'
29
+ }
30
+
31
+ return `${length} ${words.result} ${words.is} available. ${contentSelectedOption}`
32
+ }
33
+ }
34
+
35
+ state = {
36
+ bump: false,
37
+ debounced: false
38
+ }
39
+
40
+ /* eslint-disable react/no-deprecated -- https://github.com/alphagov/accessible-autocomplete/issues/418 */
41
+ componentWillMount () {
42
+ const that = this
43
+ this.debounceStatusUpdate = debounce(function () {
44
+ if (!that.state.debounced) {
45
+ const shouldSilence = !that.props.isInFocus || that.props.validChoiceMade
46
+ that.setState(({ bump }) => ({ bump: !bump, debounced: true, silenced: shouldSilence }))
47
+ }
48
+ }, statusDebounceMillis)
49
+ }
50
+
51
+ /* eslint-disable react/no-deprecated -- https://github.com/alphagov/accessible-autocomplete/issues/418 */
52
+ componentWillReceiveProps ({ queryLength }) {
53
+ this.setState({ debounced: false })
54
+ }
55
+
56
+ render () {
57
+ const {
58
+ id,
59
+ length,
60
+ queryLength,
61
+ minQueryLength,
62
+ selectedOption,
63
+ selectedOptionIndex,
64
+ tQueryTooShort,
65
+ tNoResults,
66
+ tSelectedOption,
67
+ tResults,
68
+ className
69
+ } = this.props
70
+ const { bump, debounced, silenced } = this.state
71
+
72
+ const queryTooShort = queryLength < minQueryLength
73
+ const noResults = length === 0
74
+
75
+ const contentSelectedOption = selectedOption
76
+ ? tSelectedOption(selectedOption, length, selectedOptionIndex)
77
+ : ''
78
+
79
+ let content = null
80
+ if (queryTooShort) {
81
+ content = tQueryTooShort(minQueryLength)
82
+ } else if (noResults) {
83
+ content = tNoResults()
84
+ } else {
85
+ content = tResults(length, contentSelectedOption)
86
+ }
87
+
88
+ this.debounceStatusUpdate()
89
+
90
+ return (
91
+ <div
92
+ className={className}
93
+ style={{
94
+ border: '0',
95
+ clip: 'rect(0 0 0 0)',
96
+ height: '1px',
97
+ marginBottom: '-1px',
98
+ marginRight: '-1px',
99
+ overflow: 'hidden',
100
+ padding: '0',
101
+ position: 'absolute',
102
+ whiteSpace: 'nowrap',
103
+ width: '1px'
104
+ }}
105
+ >
106
+ <div
107
+ id={id + '__status--A'}
108
+ role='status'
109
+ aria-atomic='true'
110
+ aria-live='polite'
111
+ >
112
+ {(!silenced && debounced && bump) ? content : ''}
113
+ </div>
114
+ <div
115
+ id={id + '__status--B'}
116
+ role='status'
117
+ aria-atomic='true'
118
+ aria-live='polite'
119
+ >
120
+ {(!silenced && debounced && !bump) ? content : ''}
121
+ </div>
122
+ </div>
123
+ )
124
+ }
125
+ }
@@ -0,0 +1,60 @@
1
+ import { createElement, render } from 'preact' /** @jsx createElement */
2
+ import Autocomplete from './autocomplete'
3
+
4
+ function accessibleAutocomplete (options) {
5
+ if (!options.element) { throw new Error('element is not defined') }
6
+ if (!options.id) { throw new Error('id is not defined') }
7
+ if (!options.source) { throw new Error('source is not defined') }
8
+ if (Array.isArray(options.source)) {
9
+ options.source = createSimpleEngine(options.source)
10
+ }
11
+ render(<Autocomplete {...options} />, options.element)
12
+ }
13
+
14
+ const createSimpleEngine = (values) => (query, syncResults) => {
15
+ const matches = values.filter(r => r.toLowerCase().indexOf(query.toLowerCase()) !== -1)
16
+ syncResults(matches)
17
+ }
18
+
19
+ accessibleAutocomplete.enhanceSelectElement = (configurationOptions) => {
20
+ if (!configurationOptions.selectElement) { throw new Error('selectElement is not defined') }
21
+
22
+ // Set defaults.
23
+ if (!configurationOptions.source) {
24
+ const availableOptions = [].filter.call(configurationOptions.selectElement.options, option => (option.value || configurationOptions.preserveNullOptions))
25
+ configurationOptions.source = availableOptions.map(option => option.textContent || option.innerText)
26
+ }
27
+ configurationOptions.onConfirm = configurationOptions.onConfirm || (query => {
28
+ const requestedOption = [].filter.call(configurationOptions.selectElement.options, option => (option.textContent || option.innerText) === query)[0]
29
+ if (requestedOption) { requestedOption.selected = true }
30
+ })
31
+
32
+ if (configurationOptions.selectElement.value || configurationOptions.defaultValue === undefined) {
33
+ const option = configurationOptions.selectElement.options[configurationOptions.selectElement.options.selectedIndex]
34
+ configurationOptions.defaultValue = option.textContent || option.innerText
35
+ }
36
+
37
+ if (configurationOptions.name === undefined) configurationOptions.name = ''
38
+ if (configurationOptions.id === undefined) {
39
+ if (configurationOptions.selectElement.id === undefined) {
40
+ configurationOptions.id = ''
41
+ } else {
42
+ configurationOptions.id = configurationOptions.selectElement.id
43
+ }
44
+ }
45
+ if (configurationOptions.autoselect === undefined) configurationOptions.autoselect = true
46
+
47
+ const element = document.createElement('div')
48
+
49
+ configurationOptions.selectElement.parentNode.insertBefore(element, configurationOptions.selectElement)
50
+
51
+ accessibleAutocomplete({
52
+ ...configurationOptions,
53
+ element
54
+ })
55
+
56
+ configurationOptions.selectElement.style.display = 'none'
57
+ configurationOptions.selectElement.id = configurationOptions.selectElement.id + '-select'
58
+ }
59
+
60
+ export default accessibleAutocomplete
@@ -0,0 +1,46 @@
1
+ /* global before, beforeEach, after, describe, it */
2
+
3
+ import { expect } from 'chai'
4
+ import { createElement, render } from 'preact' /** @jsx createElement */
5
+ import DropdownArrowDown from '../../src/dropdown-arrow-down'
6
+
7
+ describe('DropdownArrowDown', () => {
8
+ describe('rendering', () => {
9
+ let scratch
10
+
11
+ before(() => {
12
+ scratch = document.createElement('div');
13
+ (document.body || document.documentElement).appendChild(scratch)
14
+ })
15
+
16
+ beforeEach(() => {
17
+ scratch.innerHTML = ''
18
+ })
19
+
20
+ after(() => {
21
+ scratch.parentNode.removeChild(scratch)
22
+ scratch = null
23
+ })
24
+
25
+ describe('basic usage', () => {
26
+ it('renders an svg', () => {
27
+ render(<DropdownArrowDown />, scratch)
28
+
29
+ expect(scratch.innerHTML).to.contain('svg')
30
+ })
31
+
32
+ it('renders with a given custom class', () => {
33
+ render(<DropdownArrowDown className='foo' />, scratch)
34
+
35
+ expect(scratch.innerHTML).to.contain('class="foo"')
36
+ })
37
+
38
+ // IE issue so the dropdown svg is not focusable (tabindex won't work for this)
39
+ it('renders an svg where focusable attribute is false', () => {
40
+ render(<DropdownArrowDown />, scratch)
41
+
42
+ expect(scratch.innerHTML).to.contain('focusable="false"')
43
+ })
44
+ })
45
+ })
46
+ })