shinkansen-sprockets 1.0.28
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/.husky/pre-commit +4 -0
- package/README.md +11 -0
- package/babel.config.js +72 -0
- package/gulp.sh +42 -0
- package/index.js +7 -0
- package/lib/components/common/text-content/index.js +1 -0
- package/lib/components/description/fieldset/index.js +1 -0
- package/lib/components/description/index.js +1 -0
- package/lib/components/error-message/fieldset/index.js +1 -0
- package/lib/components/error-message/index.js +1 -0
- package/lib/components/group/check-answers/answer-title.js +1 -0
- package/lib/components/group/check-answers/answer-value.js +1 -0
- package/lib/components/group/check-answers/change-answer.js +1 -0
- package/lib/components/group/check-answers/index.js +1 -0
- package/lib/components/group/check-answers/visually-hidden-text.js +1 -0
- package/lib/components/group/error-summary/index.js +1 -0
- package/lib/components/group/fieldset/index.js +1 -0
- package/lib/components/group/index.js +1 -0
- package/lib/components/title/check-answers/index.js +1 -0
- package/lib/components/title/error-summary/index.js +1 -0
- package/lib/components/title/fieldset/index.js +1 -0
- package/lib/components/title/index.js +1 -0
- package/lib/index.js +1 -0
- package/lib/sprockets/check-answers/index.js +1 -0
- package/lib/sprockets/error-summary/index.js +1 -0
- package/lib/sprockets/fieldset/index.js +1 -0
- package/lib/sprockets/index.js +1 -0
- package/lib/transformers/check-answers/index.js +1 -0
- package/lib/transformers/common/index.js +1 -0
- package/lib/transformers/error-message/index.js +1 -0
- package/lib/transformers/error-summary/index.js +1 -0
- package/package.json +107 -0
- package/src/components/common/text-content/index.js +14 -0
- package/src/components/description/fieldset/index.js +19 -0
- package/src/components/description/index.js +61 -0
- package/src/components/error-message/fieldset/index.js +19 -0
- package/src/components/error-message/index.js +103 -0
- package/src/components/group/check-answers/answer-title.js +21 -0
- package/src/components/group/check-answers/answer-value.js +45 -0
- package/src/components/group/check-answers/change-answer.js +35 -0
- package/src/components/group/check-answers/index.js +104 -0
- package/src/components/group/check-answers/visually-hidden-text.js +25 -0
- package/src/components/group/error-summary/index.js +106 -0
- package/src/components/group/fieldset/index.js +19 -0
- package/src/components/group/index.js +42 -0
- package/src/components/title/check-answers/index.js +33 -0
- package/src/components/title/error-summary/index.js +33 -0
- package/src/components/title/fieldset/index.js +19 -0
- package/src/components/title/index.js +59 -0
- package/src/index.js +13 -0
- package/src/sprockets/check-answers/index.js +74 -0
- package/src/sprockets/error-summary/index.js +79 -0
- package/src/sprockets/fieldset/index.js +108 -0
- package/src/sprockets/index.js +86 -0
- package/src/transformers/check-answers/index.js +12 -0
- package/src/transformers/common/index.js +14 -0
- package/src/transformers/error-message/index.js +234 -0
- package/src/transformers/error-summary/index.js +234 -0
package/package.json
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
{
|
2
|
+
"name": "shinkansen-sprockets",
|
3
|
+
"version": "1.0.28",
|
4
|
+
"description": "Shinkansen Sprockets",
|
5
|
+
"keywords": [
|
6
|
+
"Shinkansen",
|
7
|
+
"Sprockets",
|
8
|
+
"Zashiki Karakuri",
|
9
|
+
"Zashiki",
|
10
|
+
"Karakuri",
|
11
|
+
"React"
|
12
|
+
],
|
13
|
+
"main": "./index.js",
|
14
|
+
"author": "Jonathan Perry for Modern Poacher Limited <modernpoacher@modernpoacher.com>",
|
15
|
+
"license": "MIT",
|
16
|
+
"engines": {
|
17
|
+
"node": ">=12.19.0"
|
18
|
+
},
|
19
|
+
"repository": {
|
20
|
+
"type": "git",
|
21
|
+
"url": "git@github.com/modernpoacher/shinkansen-sprockets.git"
|
22
|
+
},
|
23
|
+
"scripts": {
|
24
|
+
"prepublishOnly": "cross-env NODE_ENV=production npm run build",
|
25
|
+
"prebuild": "npm run clean",
|
26
|
+
"build": "cross-env DEBUG=shinkansen-sprockets npm run babel -- --ignore \"**/__tests__/**\" && npm run gulp",
|
27
|
+
"build:watch": "npm run gulp -- build:watch",
|
28
|
+
"watch": "cross-env DEBUG=shinkansen-sprockets concurrently -r \"npm run babel:watch\" \"npm run build:watch\"",
|
29
|
+
"clean": "rimraf lib",
|
30
|
+
"transform": "npm run gulp -- transform",
|
31
|
+
"transform:watch": "npm run gulp -- transform:watch",
|
32
|
+
"babel": "babel src -d lib",
|
33
|
+
"babel:watch": "npm run babel -- -w",
|
34
|
+
"gulp": "bash gulp.sh --color",
|
35
|
+
"lint": "eslint . .storybook",
|
36
|
+
"lint:fix": "npm run lint -- --fix",
|
37
|
+
"test": "cross-env NODE_ENV=test jest --collect-coverage false --verbose --run-in-band",
|
38
|
+
"storybook": "npm run build && npm run transform && start-storybook -p 6007",
|
39
|
+
"pre-commit": "npm run lint && npm test && npm run build && npm run transform && git add lib .storybook"
|
40
|
+
},
|
41
|
+
"dependencies": {
|
42
|
+
"classnames": "^2.3.1",
|
43
|
+
"debug": "^4.3.2",
|
44
|
+
"immutable": "3.8.2"
|
45
|
+
},
|
46
|
+
"devDependencies": {
|
47
|
+
"@babel/cli": "^7.15.4",
|
48
|
+
"@babel/core": "^7.15.5",
|
49
|
+
"@babel/eslint-parser": "^7.15.4",
|
50
|
+
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
51
|
+
"@babel/plugin-proposal-export-default-from": "^7.14.5",
|
52
|
+
"@babel/plugin-proposal-export-namespace-from": "^7.14.5",
|
53
|
+
"@babel/plugin-transform-runtime": "^7.15.0",
|
54
|
+
"@babel/preset-env": "^7.15.6",
|
55
|
+
"@babel/preset-react": "^7.14.5",
|
56
|
+
"@babel/register": "^7.15.3",
|
57
|
+
"@modernpoacher/design-system": "0.0.383",
|
58
|
+
"@storybook/addon-actions": "^6.3.8",
|
59
|
+
"@storybook/addon-essentials": "^6.3.8",
|
60
|
+
"@storybook/addon-links": "^6.3.8",
|
61
|
+
"@storybook/react": "^6.3.8",
|
62
|
+
"autoprefixer": "^10.3.4",
|
63
|
+
"babel-jest": "^27.2.0",
|
64
|
+
"babel-loader": "^8.2.2",
|
65
|
+
"babel-plugin-module-resolver": "^4.1.0",
|
66
|
+
"concurrently": "^6.2.1",
|
67
|
+
"core-js": "^3.17.3",
|
68
|
+
"cross-env": "^7.0.3",
|
69
|
+
"cssnano": "^5.0.8",
|
70
|
+
"dart-sass": "^1.25.0",
|
71
|
+
"del": "^6.0.0",
|
72
|
+
"enzyme": "^3.11.0",
|
73
|
+
"enzyme-adapter-react-16": "^1.15.6",
|
74
|
+
"eslint": "^7.32.0",
|
75
|
+
"eslint-config-standard": "^16.0.3",
|
76
|
+
"eslint-import-resolver-babel-module": "^5.3.1",
|
77
|
+
"eslint-plugin-import": "^2.24.2",
|
78
|
+
"eslint-plugin-node": "^11.1.0",
|
79
|
+
"eslint-plugin-promise": "^5.1.0",
|
80
|
+
"eslint-plugin-react": "^7.25.2",
|
81
|
+
"glob-all": "^3.2.1",
|
82
|
+
"gulp": "^4.0.2",
|
83
|
+
"gulp-clean-css": "^4.3.0",
|
84
|
+
"gulp-css-purge": "^3.0.9",
|
85
|
+
"gulp-debug": "^4.0.0",
|
86
|
+
"gulp-postcss": "^9.0.1",
|
87
|
+
"gulp-rename": "^2.0.0",
|
88
|
+
"gulp-sass": "^5.0.0",
|
89
|
+
"gulp-sourcemaps": "^3.0.0",
|
90
|
+
"husky": "^7.0.2",
|
91
|
+
"jest": "^27.2.0",
|
92
|
+
"postcss": "^8.3.6",
|
93
|
+
"postcss-easy-import": "^3.0.0",
|
94
|
+
"postcss-map": "^0.11.0",
|
95
|
+
"postcss-normalize": "^10.0.1",
|
96
|
+
"postcss-scss": "^4.0.0",
|
97
|
+
"prop-types": "15.7.2",
|
98
|
+
"react": "16.14.0",
|
99
|
+
"react-dom": "16.14.0",
|
100
|
+
"react-router": "5.2.0",
|
101
|
+
"react-router-dom": "5.2.0",
|
102
|
+
"react-test-renderer": "16.14.0",
|
103
|
+
"regenerator-runtime": "^0.13.9",
|
104
|
+
"rimraf": "^3.0.2",
|
105
|
+
"vinyl-paths": "3.0.1"
|
106
|
+
}
|
107
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PropTypes from 'prop-types'
|
3
|
+
|
4
|
+
const TextContent = ({ textContent }) => (
|
5
|
+
<span className='text-content'>
|
6
|
+
{textContent}
|
7
|
+
</span>
|
8
|
+
)
|
9
|
+
|
10
|
+
TextContent.propTypes = {
|
11
|
+
textContent: PropTypes.string.isRequired
|
12
|
+
}
|
13
|
+
|
14
|
+
export default TextContent
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/**
|
2
|
+
* FieldsetDescription component
|
3
|
+
*/
|
4
|
+
import classnames from 'classnames'
|
5
|
+
import Description from 'shinkansen-sprockets/components/description'
|
6
|
+
|
7
|
+
export default class FieldsetDescription extends Description {
|
8
|
+
getClassName () {
|
9
|
+
return classnames(super.getClassName(), 'fieldset')
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
FieldsetDescription.propTypes = {
|
14
|
+
...Description.propTypes
|
15
|
+
}
|
16
|
+
|
17
|
+
FieldsetDescription.defaultProps = {
|
18
|
+
...Description.defaultProps
|
19
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
/**
|
2
|
+
* Description component
|
3
|
+
*/
|
4
|
+
import React, { Component } from 'react'
|
5
|
+
import PropTypes from 'prop-types'
|
6
|
+
|
7
|
+
import TextContent from 'shinkansen-sprockets/components/common/text-content'
|
8
|
+
|
9
|
+
export default class Description extends Component {
|
10
|
+
hasTextContent () {
|
11
|
+
const { description } = this.props
|
12
|
+
|
13
|
+
return !!description
|
14
|
+
}
|
15
|
+
|
16
|
+
getTextContent () {
|
17
|
+
const { description } = this.props
|
18
|
+
|
19
|
+
return description
|
20
|
+
}
|
21
|
+
|
22
|
+
getClassName () {
|
23
|
+
return 'description'
|
24
|
+
}
|
25
|
+
|
26
|
+
shouldComponentUpdate (props) {
|
27
|
+
return (
|
28
|
+
(props.description !== this.props.description)
|
29
|
+
)
|
30
|
+
}
|
31
|
+
|
32
|
+
renderTextContent () {
|
33
|
+
if (this.hasTextContent()) {
|
34
|
+
const textContent = this.getTextContent()
|
35
|
+
|
36
|
+
return (
|
37
|
+
<TextContent textContent={textContent} />
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
41
|
+
return null
|
42
|
+
}
|
43
|
+
|
44
|
+
render () {
|
45
|
+
const { description } = this.props
|
46
|
+
|
47
|
+
if (description) {
|
48
|
+
return (
|
49
|
+
<span className={this.getClassName()}>
|
50
|
+
{this.renderTextContent()}
|
51
|
+
</span>
|
52
|
+
)
|
53
|
+
}
|
54
|
+
|
55
|
+
return null
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
Description.propTypes = {
|
60
|
+
description: PropTypes.string
|
61
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/**
|
2
|
+
* FieldsetErrorMessage component
|
3
|
+
*/
|
4
|
+
import classnames from 'classnames'
|
5
|
+
import ErrorMessage from 'shinkansen-sprockets/components/error-message'
|
6
|
+
|
7
|
+
export default class FieldsetErrorMessage extends ErrorMessage {
|
8
|
+
getClassName () {
|
9
|
+
return classnames(super.getClassName(), 'fieldset')
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
FieldsetErrorMessage.propTypes = {
|
14
|
+
...ErrorMessage.propTypes
|
15
|
+
}
|
16
|
+
|
17
|
+
FieldsetErrorMessage.defaultProps = {
|
18
|
+
...ErrorMessage.defaultProps
|
19
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
/**
|
2
|
+
* ErrorMessage component
|
3
|
+
*/
|
4
|
+
import React, { Component } from 'react'
|
5
|
+
import PropTypes from 'prop-types'
|
6
|
+
import Immutable from 'immutable'
|
7
|
+
|
8
|
+
import transform from 'shinkansen-sprockets/transformers/error-message'
|
9
|
+
|
10
|
+
import TextContent from 'shinkansen-sprockets/components/common/text-content'
|
11
|
+
|
12
|
+
export default class ErrorMessage extends Component {
|
13
|
+
state = { errorMessage: Immutable.Map() }
|
14
|
+
|
15
|
+
hasTextContent () {
|
16
|
+
const { errorMessage } = this.props
|
17
|
+
|
18
|
+
const {
|
19
|
+
text
|
20
|
+
} = transform(errorMessage)
|
21
|
+
|
22
|
+
return !!text
|
23
|
+
}
|
24
|
+
|
25
|
+
getTextContent () {
|
26
|
+
const { errorMessage } = this.props
|
27
|
+
const {
|
28
|
+
text
|
29
|
+
} = transform(errorMessage)
|
30
|
+
|
31
|
+
return text
|
32
|
+
}
|
33
|
+
|
34
|
+
getClassName () {
|
35
|
+
return 'error-message'
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Convert latest 'props' to an Immutable.Map() and store in 'state'
|
40
|
+
*
|
41
|
+
* @param {Object} props Latest props
|
42
|
+
* @param {Object} state Current state
|
43
|
+
*/
|
44
|
+
static getDerivedStateFromProps ({ errorMessage }, { errorMessage: E }) {
|
45
|
+
const e = Immutable.Map(errorMessage)
|
46
|
+
|
47
|
+
return {
|
48
|
+
errorMessage: Immutable.is(E, e) ? E : e
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Compare latest 'props' via 'state' for changes to 'errorMessage'
|
54
|
+
*
|
55
|
+
* @param {Object} props Latest props
|
56
|
+
* @param {Object} state Latest state
|
57
|
+
*/
|
58
|
+
shouldComponentUpdate (props, state) {
|
59
|
+
const {
|
60
|
+
errorMessage: e
|
61
|
+
} = state
|
62
|
+
|
63
|
+
const {
|
64
|
+
errorMessage: E
|
65
|
+
} = this.state
|
66
|
+
|
67
|
+
return (e !== E)
|
68
|
+
}
|
69
|
+
|
70
|
+
renderTextContent () {
|
71
|
+
if (this.hasTextContent()) {
|
72
|
+
const textContent = this.getTextContent()
|
73
|
+
|
74
|
+
return (
|
75
|
+
<TextContent textContent={textContent} />
|
76
|
+
)
|
77
|
+
}
|
78
|
+
|
79
|
+
return null
|
80
|
+
}
|
81
|
+
|
82
|
+
render () {
|
83
|
+
const { errorMessage } = this.props
|
84
|
+
|
85
|
+
if (errorMessage) {
|
86
|
+
return (
|
87
|
+
<span className={this.getClassName()}>
|
88
|
+
{this.renderTextContent()}
|
89
|
+
</span>
|
90
|
+
)
|
91
|
+
}
|
92
|
+
|
93
|
+
return null
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
ErrorMessage.propTypes = {
|
98
|
+
errorMessage: PropTypes.shape({
|
99
|
+
type: PropTypes.string.isRequired,
|
100
|
+
params: PropTypes.shape().isRequired,
|
101
|
+
uri: PropTypes.string.isRequired
|
102
|
+
})
|
103
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PropTypes from 'prop-types'
|
3
|
+
import debug from 'debug'
|
4
|
+
|
5
|
+
const log = debug('shinkansen-sprockets:components:group:check-answers')
|
6
|
+
|
7
|
+
export default function SummaryTitle ({ answer: { title } }) {
|
8
|
+
log('SummaryTitle')
|
9
|
+
|
10
|
+
return (
|
11
|
+
<dt className='answer-title'>
|
12
|
+
{title}
|
13
|
+
</dt>
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
SummaryTitle.propTypes = {
|
18
|
+
answer: PropTypes.shape({
|
19
|
+
title: PropTypes.string.isRequired
|
20
|
+
}).isRequired
|
21
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PropTypes from 'prop-types'
|
3
|
+
import debug from 'debug'
|
4
|
+
|
5
|
+
const log = debug('shinkansen-sprockets:components:group:check-answers')
|
6
|
+
|
7
|
+
function getAnswerValue (value) {
|
8
|
+
if (Array.isArray(value)) {
|
9
|
+
const n = value.length - 1
|
10
|
+
|
11
|
+
return (
|
12
|
+
value
|
13
|
+
.reduce((a, v, i) => {
|
14
|
+
const s = String(v)
|
15
|
+
|
16
|
+
return (i !== n)
|
17
|
+
? a.concat(s).concat(<br key={i} />)
|
18
|
+
: a.concat(s)
|
19
|
+
}, [])
|
20
|
+
)
|
21
|
+
}
|
22
|
+
|
23
|
+
return String(value)
|
24
|
+
}
|
25
|
+
|
26
|
+
export default function SummaryValue ({ answer: { value } }) {
|
27
|
+
log('SummaryValue')
|
28
|
+
|
29
|
+
return (
|
30
|
+
<dd className='answer-value'>
|
31
|
+
{getAnswerValue(value)}
|
32
|
+
</dd>
|
33
|
+
)
|
34
|
+
}
|
35
|
+
|
36
|
+
SummaryValue.propTypes = {
|
37
|
+
answer: PropTypes.shape({
|
38
|
+
value: PropTypes.oneOfType([
|
39
|
+
PropTypes.string,
|
40
|
+
PropTypes.arrayOf(
|
41
|
+
PropTypes.string
|
42
|
+
)
|
43
|
+
]).isRequired
|
44
|
+
}).isRequired
|
45
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PropTypes from 'prop-types'
|
3
|
+
import debug from 'debug'
|
4
|
+
|
5
|
+
import {
|
6
|
+
Link
|
7
|
+
} from 'react-router-dom'
|
8
|
+
|
9
|
+
import TextContent from 'shinkansen-sprockets/components/common/text-content'
|
10
|
+
|
11
|
+
import VisuallyHiddenText from './visually-hidden-text'
|
12
|
+
|
13
|
+
const log = debug('shinkansen-sprockets:components:group:check-answers')
|
14
|
+
|
15
|
+
export default function ChangeAnswer ({ changeAnswer: { href, text, visuallyHiddenText } }) {
|
16
|
+
log('ChangeAnswer')
|
17
|
+
|
18
|
+
return (
|
19
|
+
<dd className='change-answer'>
|
20
|
+
<Link to={href}>
|
21
|
+
<TextContent textContent={text} />
|
22
|
+
{String.fromCharCode(32)}
|
23
|
+
<VisuallyHiddenText visuallyHiddenText={visuallyHiddenText} />
|
24
|
+
</Link>
|
25
|
+
</dd>
|
26
|
+
)
|
27
|
+
}
|
28
|
+
|
29
|
+
ChangeAnswer.propTypes = {
|
30
|
+
changeAnswer: PropTypes.shape({
|
31
|
+
href: PropTypes.string.isRequired,
|
32
|
+
text: PropTypes.string.isRequired,
|
33
|
+
visuallyHiddenText: PropTypes.string.isRequired
|
34
|
+
}).isRequired
|
35
|
+
}
|
@@ -0,0 +1,104 @@
|
|
1
|
+
/**
|
2
|
+
* CheckAnswersGroup component
|
3
|
+
*/
|
4
|
+
import React from 'react'
|
5
|
+
import PropTypes from 'prop-types'
|
6
|
+
import Immutable from 'immutable'
|
7
|
+
import classnames from 'classnames'
|
8
|
+
|
9
|
+
import debug from 'debug'
|
10
|
+
|
11
|
+
import Group from 'shinkansen-sprockets/components/group'
|
12
|
+
|
13
|
+
import {
|
14
|
+
getKey
|
15
|
+
} from 'shinkansen-sprockets/transformers/common'
|
16
|
+
|
17
|
+
import AnswerTitle from './answer-title'
|
18
|
+
import AnswerValue from './answer-value'
|
19
|
+
import ChangeAnswer from './change-answer'
|
20
|
+
|
21
|
+
const log = debug('shinkansen-sprockets:components:group:check-answers')
|
22
|
+
|
23
|
+
/* eslint-disable-next-line react/prop-types */
|
24
|
+
function render ({ params: { answer, changeAnswer: { href, text, ...changeAnswer } } }, index) {
|
25
|
+
log('render')
|
26
|
+
|
27
|
+
return (
|
28
|
+
<div key={getKey(href, text, index)} className='answer'>
|
29
|
+
<AnswerTitle answer={answer} />
|
30
|
+
<AnswerValue answer={answer} />
|
31
|
+
<ChangeAnswer
|
32
|
+
changeAnswer={{ ...changeAnswer, href, text }}
|
33
|
+
/>
|
34
|
+
</div>
|
35
|
+
)
|
36
|
+
}
|
37
|
+
|
38
|
+
export default class CheckAnswersGroup extends Group {
|
39
|
+
state = {}
|
40
|
+
|
41
|
+
getClassName () {
|
42
|
+
return classnames(super.getClassName(), 'check-answers')
|
43
|
+
}
|
44
|
+
|
45
|
+
/**
|
46
|
+
* Convert latest 'props' to an Immutable.Map() and store in 'state'
|
47
|
+
*
|
48
|
+
* @param {Object} props Latest props
|
49
|
+
* @param {Object} state Current state
|
50
|
+
*/
|
51
|
+
static getDerivedStateFromProps ({ checkAnswers }, { checkAnswers: C }) {
|
52
|
+
const c = Immutable.Map(checkAnswers)
|
53
|
+
|
54
|
+
return {
|
55
|
+
checkAnswers: Immutable.is(C, c) ? C : c
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Compare latest 'props' via 'state' for changes to 'checkAnswers'
|
61
|
+
*
|
62
|
+
* @param {Object} props Latest props
|
63
|
+
* @param {Object} state Latest state
|
64
|
+
*/
|
65
|
+
shouldComponentUpdate (props, state) {
|
66
|
+
const {
|
67
|
+
checkAnswers: c
|
68
|
+
} = state
|
69
|
+
|
70
|
+
const {
|
71
|
+
checkAnswers: C
|
72
|
+
} = this.state
|
73
|
+
|
74
|
+
return (c !== C)
|
75
|
+
}
|
76
|
+
|
77
|
+
render () {
|
78
|
+
const {
|
79
|
+
checkAnswers
|
80
|
+
} = this.props
|
81
|
+
|
82
|
+
if (checkAnswers.length) {
|
83
|
+
return (
|
84
|
+
<dl
|
85
|
+
className={this.getClassName()}
|
86
|
+
ref={this.setDOMNode}>
|
87
|
+
{checkAnswers.map(render)}
|
88
|
+
</dl>
|
89
|
+
)
|
90
|
+
}
|
91
|
+
|
92
|
+
return null
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
CheckAnswersGroup.propTypes = {
|
97
|
+
...Group.propTypes,
|
98
|
+
checkAnswers: PropTypes.array
|
99
|
+
}
|
100
|
+
|
101
|
+
CheckAnswersGroup.defaultProps = {
|
102
|
+
...Group.defaultProps,
|
103
|
+
checkAnswers: []
|
104
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PropTypes from 'prop-types'
|
3
|
+
import debug from 'debug'
|
4
|
+
|
5
|
+
const log = debug('shinkansen-sprockets:components:group:check-answers')
|
6
|
+
|
7
|
+
export default function VisuallyHiddenText ({ visuallyHiddenText }) {
|
8
|
+
log('VisuallyHiddenText')
|
9
|
+
|
10
|
+
if (visuallyHiddenText) {
|
11
|
+
return (
|
12
|
+
<span className='visually-hidden-text'>
|
13
|
+
{visuallyHiddenText.toLowerCase()}
|
14
|
+
</span>
|
15
|
+
)
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
VisuallyHiddenText.propTypes = {
|
20
|
+
visuallyHiddenText: PropTypes.string
|
21
|
+
}
|
22
|
+
|
23
|
+
VisuallyHiddenText.defaultProps = {
|
24
|
+
visuallyHiddenText: ''
|
25
|
+
}
|
@@ -0,0 +1,106 @@
|
|
1
|
+
/**
|
2
|
+
* ErrorSummaryGroup component
|
3
|
+
*/
|
4
|
+
import React from 'react'
|
5
|
+
import PropTypes from 'prop-types'
|
6
|
+
import Immutable from 'immutable'
|
7
|
+
import classnames from 'classnames'
|
8
|
+
|
9
|
+
import debug from 'debug'
|
10
|
+
|
11
|
+
import Group from 'shinkansen-sprockets/components/group'
|
12
|
+
|
13
|
+
import transform from 'shinkansen-sprockets/transformers/error-summary'
|
14
|
+
import {
|
15
|
+
getKey
|
16
|
+
} from 'shinkansen-sprockets/transformers/common'
|
17
|
+
|
18
|
+
import TextContent from 'shinkansen-sprockets/components/common/text-content'
|
19
|
+
|
20
|
+
const log = debug('shinkansen-sprockets:components:group:error-summary')
|
21
|
+
|
22
|
+
/* eslint-disable-next-line react/prop-types */
|
23
|
+
function render (error, index) {
|
24
|
+
log('render')
|
25
|
+
|
26
|
+
const {
|
27
|
+
href,
|
28
|
+
text
|
29
|
+
} = transform(error)
|
30
|
+
|
31
|
+
return (
|
32
|
+
<li key={getKey(href, text, index)} className='error'>
|
33
|
+
<a href={href}>
|
34
|
+
<TextContent textContent={text} />
|
35
|
+
</a>
|
36
|
+
</li>
|
37
|
+
)
|
38
|
+
}
|
39
|
+
|
40
|
+
export default class ErrorSummaryGroup extends Group {
|
41
|
+
state = {}
|
42
|
+
|
43
|
+
getClassName () {
|
44
|
+
return classnames(super.getClassName(), 'error-summary')
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Convert latest 'props' to an Immutable.Map() and store in 'state'
|
49
|
+
*
|
50
|
+
* @param {Object} props Latest props
|
51
|
+
* @param {Object} state Current state
|
52
|
+
*/
|
53
|
+
static getDerivedStateFromProps ({ errorSummary }, { errorSummary: E }) {
|
54
|
+
const e = Immutable.Map(errorSummary)
|
55
|
+
|
56
|
+
return {
|
57
|
+
errorSummary: Immutable.is(E, e) ? E : e
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Compare latest 'props' via 'state' for changes to 'errorSummary'
|
63
|
+
*
|
64
|
+
* @param {Object} props Latest props
|
65
|
+
* @param {Object} state Latest state
|
66
|
+
*/
|
67
|
+
shouldComponentUpdate (props, state) {
|
68
|
+
const {
|
69
|
+
errorSummary: e
|
70
|
+
} = state
|
71
|
+
|
72
|
+
const {
|
73
|
+
errorSummary: E
|
74
|
+
} = this.state
|
75
|
+
|
76
|
+
return (e !== E)
|
77
|
+
}
|
78
|
+
|
79
|
+
render () {
|
80
|
+
const {
|
81
|
+
errorSummary
|
82
|
+
} = this.props
|
83
|
+
|
84
|
+
if (errorSummary.length) {
|
85
|
+
return (
|
86
|
+
<ul
|
87
|
+
className={this.getClassName()}
|
88
|
+
ref={this.setDOMNode}>
|
89
|
+
{errorSummary.map(render)}
|
90
|
+
</ul>
|
91
|
+
)
|
92
|
+
}
|
93
|
+
|
94
|
+
return null
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
ErrorSummaryGroup.propTypes = {
|
99
|
+
...Group.propTypes,
|
100
|
+
errorSummary: PropTypes.array
|
101
|
+
}
|
102
|
+
|
103
|
+
ErrorSummaryGroup.defaultProps = {
|
104
|
+
...Group.defaultProps,
|
105
|
+
errorSummary: []
|
106
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/**
|
2
|
+
* FieldsetGroup component
|
3
|
+
*/
|
4
|
+
import classnames from 'classnames'
|
5
|
+
import Group from 'shinkansen-sprockets/components/group'
|
6
|
+
|
7
|
+
export default class FieldsetGroup extends Group {
|
8
|
+
getClassName () {
|
9
|
+
return classnames(super.getClassName(), 'fieldset')
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
FieldsetGroup.propTypes = {
|
14
|
+
...Group.propTypes
|
15
|
+
}
|
16
|
+
|
17
|
+
FieldsetGroup.defaultProps = {
|
18
|
+
...Group.defaultProps
|
19
|
+
}
|