govuk_publishing_components 43.4.0 → 43.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/govuk_publishing_components/version.rb +1 -1
  3. data/node_modules/accessible-autocomplete/CHANGELOG.md +390 -0
  4. data/node_modules/accessible-autocomplete/CODEOWNERS +2 -0
  5. data/node_modules/accessible-autocomplete/CONTRIBUTING.md +161 -0
  6. data/node_modules/accessible-autocomplete/LICENSE.txt +20 -0
  7. data/node_modules/accessible-autocomplete/Procfile +1 -0
  8. data/node_modules/accessible-autocomplete/README.md +490 -0
  9. data/node_modules/accessible-autocomplete/accessibility-criteria.md +42 -0
  10. data/node_modules/accessible-autocomplete/app.json +15 -0
  11. data/node_modules/accessible-autocomplete/babel.config.js +29 -0
  12. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.css +3 -0
  13. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.css.map +1 -0
  14. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.js +2 -0
  15. data/node_modules/accessible-autocomplete/dist/accessible-autocomplete.min.js.map +1 -0
  16. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.preact.min.js +2 -0
  17. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.preact.min.js.map +1 -0
  18. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.react.min.js +2 -0
  19. data/node_modules/accessible-autocomplete/dist/lib/accessible-autocomplete.react.min.js.map +1 -0
  20. data/node_modules/accessible-autocomplete/examples/form-single.html +379 -0
  21. data/node_modules/accessible-autocomplete/examples/form.html +673 -0
  22. data/node_modules/accessible-autocomplete/examples/index.html +738 -0
  23. data/node_modules/accessible-autocomplete/examples/preact/index.html +346 -0
  24. data/node_modules/accessible-autocomplete/examples/react/index.html +347 -0
  25. data/node_modules/accessible-autocomplete/package.json +93 -0
  26. data/node_modules/accessible-autocomplete/postcss.config.js +16 -0
  27. data/node_modules/accessible-autocomplete/preact.js +1 -0
  28. data/node_modules/accessible-autocomplete/react.js +1 -0
  29. data/node_modules/accessible-autocomplete/scripts/check-staged.mjs +16 -0
  30. data/node_modules/accessible-autocomplete/src/autocomplete.css +167 -0
  31. data/node_modules/accessible-autocomplete/src/autocomplete.js +608 -0
  32. data/node_modules/accessible-autocomplete/src/dropdown-arrow-down.js +11 -0
  33. data/node_modules/accessible-autocomplete/src/status.js +125 -0
  34. data/node_modules/accessible-autocomplete/src/wrapper.js +60 -0
  35. data/node_modules/accessible-autocomplete/test/functional/dropdown-arrow-down.js +46 -0
  36. data/node_modules/accessible-autocomplete/test/functional/index.js +793 -0
  37. data/node_modules/accessible-autocomplete/test/functional/wrapper.js +339 -0
  38. data/node_modules/accessible-autocomplete/test/integration/index.js +309 -0
  39. data/node_modules/accessible-autocomplete/test/karma.config.js +46 -0
  40. data/node_modules/accessible-autocomplete/test/wdio.config.js +123 -0
  41. data/node_modules/accessible-autocomplete/webpack.config.mjs +244 -0
  42. metadata +40 -1
@@ -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
+ })