@comicrelief/component-library 5.6.1 → 5.7.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/dist/components/Atoms/ButtonWithStates/ButtonWithStates.js +91 -0
- package/dist/components/Atoms/ButtonWithStates/ButtonWithStates.md +13 -0
- package/dist/components/Atoms/Link/Link.js +13 -2
- package/dist/components/Molecules/Lookup/Lookup.js +201 -0
- package/dist/components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup.js +112 -0
- package/dist/components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup.md +7 -0
- package/dist/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +8 -0
- package/dist/index.js +24 -0
- package/package.json +2 -1
- package/src/components/Atoms/ButtonWithStates/ButtonWithStates.js +64 -0
- package/src/components/Atoms/ButtonWithStates/ButtonWithStates.md +13 -0
- package/src/components/Atoms/Link/Link.js +7 -2
- package/src/components/Molecules/Lookup/Lookup.js +148 -0
- package/src/components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup.js +63 -0
- package/src/components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup.md +7 -0
- package/src/components/Molecules/SingleMessage/__snapshots__/SingleMessage.test.js.snap +8 -0
- package/src/index.js +3 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
|
|
11
|
+
|
|
12
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
|
|
13
|
+
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
15
|
+
|
|
16
|
+
var _styledComponents = _interopRequireDefault(require("styled-components"));
|
|
17
|
+
|
|
18
|
+
var _ScaleLoader = _interopRequireDefault(require("react-spinners/ScaleLoader"));
|
|
19
|
+
|
|
20
|
+
var _spacing = _interopRequireDefault(require("../../../theme/shared/spacing"));
|
|
21
|
+
|
|
22
|
+
var _Button = _interopRequireDefault(require("../Button/Button"));
|
|
23
|
+
|
|
24
|
+
var _excluded = ["children", "loadingText", "loading", "disabled"];
|
|
25
|
+
|
|
26
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
27
|
+
|
|
28
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
29
|
+
|
|
30
|
+
var ButtonWithDisabledState = (0, _styledComponents.default)(_Button.default).withConfig({
|
|
31
|
+
displayName: "ButtonWithStates__ButtonWithDisabledState",
|
|
32
|
+
componentId: "sc-7gb81g-0"
|
|
33
|
+
})(["&:disabled{cursor:not-allowed;opacity:0.75;}"]);
|
|
34
|
+
|
|
35
|
+
var LoaderContainer = _styledComponents.default.div.withConfig({
|
|
36
|
+
displayName: "ButtonWithStates__LoaderContainer",
|
|
37
|
+
componentId: "sc-7gb81g-1"
|
|
38
|
+
})(["", ""], function (_ref) {
|
|
39
|
+
var withMargin = _ref.withMargin;
|
|
40
|
+
return withMargin ? "\n margin-top: ".concat((0, _spacing.default)('xsm'), ";\n margin-left: ").concat((0, _spacing.default)('md'), ";\n") : '';
|
|
41
|
+
}); // A button with loading and disabled states.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
var ButtonWithStates = /*#__PURE__*/_react.default.forwardRef(function (_ref2, ref) {
|
|
45
|
+
var children = _ref2.children,
|
|
46
|
+
loadingText = _ref2.loadingText,
|
|
47
|
+
loading = _ref2.loading,
|
|
48
|
+
disabled = _ref2.disabled,
|
|
49
|
+
rest = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
|
|
50
|
+
|
|
51
|
+
var _useState = (0, _react.useState)(null),
|
|
52
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
53
|
+
loaderColour = _useState2[0],
|
|
54
|
+
setLoaderColour = _useState2[1]; // Can't see a simpler way to get the button's text colour, without reading the value
|
|
55
|
+
// via JavaScript.
|
|
56
|
+
// (e.g. the `theme.buttonColours` helper returns a CSS string split into an array -
|
|
57
|
+
// don't really want to be parsing that.)
|
|
58
|
+
// (And can't use inherit because ScaleLoader's color prop is actually setting its
|
|
59
|
+
// background color.)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
var getLoaderColour = (0, _react.useCallback)(function (node) {
|
|
63
|
+
if (node && typeof window.getComputedStyle === 'function') {
|
|
64
|
+
var textColour = window.getComputedStyle(node).color;
|
|
65
|
+
|
|
66
|
+
if (textColour) {
|
|
67
|
+
setLoaderColour(textColour);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}, []);
|
|
71
|
+
return /*#__PURE__*/_react.default.createElement(ButtonWithDisabledState, Object.assign({
|
|
72
|
+
ref: ref,
|
|
73
|
+
disabled: disabled
|
|
74
|
+
}, rest), loading ? loadingText : children, /*#__PURE__*/_react.default.createElement(LoaderContainer, {
|
|
75
|
+
ref: getLoaderColour,
|
|
76
|
+
withMargin: loading
|
|
77
|
+
}, /*#__PURE__*/_react.default.createElement(_ScaleLoader.default, {
|
|
78
|
+
height: 16,
|
|
79
|
+
width: 2,
|
|
80
|
+
loading: loading,
|
|
81
|
+
color: loaderColour
|
|
82
|
+
})));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
ButtonWithStates.defaultProps = {
|
|
86
|
+
loading: false,
|
|
87
|
+
disabled: false,
|
|
88
|
+
loadingText: 'Loading'
|
|
89
|
+
};
|
|
90
|
+
var _default = ButtonWithStates;
|
|
91
|
+
exports.default = _default;
|
|
@@ -7,9 +7,11 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
});
|
|
8
8
|
exports.default = void 0;
|
|
9
9
|
|
|
10
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
|
|
11
|
+
|
|
10
12
|
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
|
|
11
13
|
|
|
12
|
-
var _react =
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
13
15
|
|
|
14
16
|
var _Link = _interopRequireWildcard(require("./Link.style"));
|
|
15
17
|
|
|
@@ -37,13 +39,19 @@ var Link = function Link(_ref) {
|
|
|
37
39
|
iconFirst = _ref.iconFirst,
|
|
38
40
|
rest = (0, _objectWithoutProperties2.default)(_ref, _excluded);
|
|
39
41
|
|
|
42
|
+
var _useState = (0, _react.useState)(''),
|
|
43
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
44
|
+
documentHost = _useState2[0],
|
|
45
|
+
setDocumentHost = _useState2[1];
|
|
40
46
|
/**
|
|
41
47
|
* If we haven't specifically set the target via props, check if
|
|
42
48
|
* this is an internal link OR on our whitelist before making it a '_self' link
|
|
43
49
|
*/
|
|
50
|
+
|
|
51
|
+
|
|
44
52
|
if (target === null) {
|
|
45
53
|
// Use our helper function to determine the raw domains to compare
|
|
46
|
-
var currentDomain = (0, _internalLinkHelper.getDomain)(
|
|
54
|
+
var currentDomain = (0, _internalLinkHelper.getDomain)(documentHost);
|
|
47
55
|
var linkDomain = (0, _internalLinkHelper.getDomain)(href); // Additional check for applications that need more control
|
|
48
56
|
|
|
49
57
|
var isWhiteListOverridden = rest.overrideWhiteList === true;
|
|
@@ -61,6 +69,9 @@ var Link = function Link(_ref) {
|
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
var hasIcon = icon !== null;
|
|
72
|
+
(0, _react.useEffect)(function () {
|
|
73
|
+
setDocumentHost(document.location.host);
|
|
74
|
+
}, []);
|
|
64
75
|
return /*#__PURE__*/_react.default.createElement(_Link.default, Object.assign({}, rest, {
|
|
65
76
|
color: color,
|
|
66
77
|
href: href,
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
11
|
+
|
|
12
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/asyncToGenerator"));
|
|
13
|
+
|
|
14
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/slicedToArray"));
|
|
15
|
+
|
|
16
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
|
|
17
|
+
|
|
18
|
+
var _styledComponents = _interopRequireWildcard(require("styled-components"));
|
|
19
|
+
|
|
20
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
21
|
+
|
|
22
|
+
var _TextInputWithDropdown = _interopRequireDefault(require("../../Atoms/TextInputWithDropdown/TextInputWithDropdown"));
|
|
23
|
+
|
|
24
|
+
var _spacing = _interopRequireDefault(require("../../../theme/shared/spacing"));
|
|
25
|
+
|
|
26
|
+
var _ButtonWithStates = _interopRequireDefault(require("../../Atoms/ButtonWithStates/ButtonWithStates"));
|
|
27
|
+
|
|
28
|
+
var _excluded = ["name", "label", "placeholder", "buttonText", "lookupHandler", "mapOptionToString", "onSelect", "noResultsMessage", "dropdownInstruction"];
|
|
29
|
+
|
|
30
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
31
|
+
|
|
32
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
33
|
+
|
|
34
|
+
var StyledButton = (0, _styledComponents.default)(_ButtonWithStates.default).withConfig({
|
|
35
|
+
displayName: "Lookup__StyledButton",
|
|
36
|
+
componentId: "sc-uu5bpv-0"
|
|
37
|
+
})(["", ""], function (_ref) {
|
|
38
|
+
var theme = _ref.theme;
|
|
39
|
+
return (0, _styledComponents.css)(["color:", ";border:2px solid ", ";background-color:", ";padding-left:", ";padding-right:", ";&:hover{color:", ";background-color:", ";}"], theme.color('grey_dark'), theme.color('grey_dark'), theme.color('white'), (0, _spacing.default)('lg'), (0, _spacing.default)('lg'), theme.color('grey_dark'), theme.color('white'));
|
|
40
|
+
});
|
|
41
|
+
var KEY_CODE_ENTER = 13;
|
|
42
|
+
/**
|
|
43
|
+
* A simple lookup component
|
|
44
|
+
*
|
|
45
|
+
* The `lookupHandler` should be an async function which is called when a lookup is triggered
|
|
46
|
+
* (either by hitting enter or clicking the button)
|
|
47
|
+
*
|
|
48
|
+
* It will receive the current search term and should:
|
|
49
|
+
* - take care of any validation on the search term
|
|
50
|
+
* - perform the actual lookup request
|
|
51
|
+
* - return an array of options (or an empty array if none were found)
|
|
52
|
+
* - only throw errors with user-friendly messages
|
|
53
|
+
*
|
|
54
|
+
* Any errors thrown will be caught and the message will be displayed to the user.
|
|
55
|
+
*
|
|
56
|
+
* The `onSelect` function will receive the chosen option.
|
|
57
|
+
*
|
|
58
|
+
* @param name
|
|
59
|
+
* @param label
|
|
60
|
+
* @param placeholder
|
|
61
|
+
* @param buttonText
|
|
62
|
+
* @param lookupHandler
|
|
63
|
+
* @param mapOptionToString
|
|
64
|
+
* @param onSelect
|
|
65
|
+
* @param noResultsMessage
|
|
66
|
+
* @param dropdownInstruction
|
|
67
|
+
* @param rest
|
|
68
|
+
* @returns {JSX.Element}
|
|
69
|
+
* @constructor
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
var Lookup = function Lookup(_ref2) {
|
|
73
|
+
var name = _ref2.name,
|
|
74
|
+
label = _ref2.label,
|
|
75
|
+
placeholder = _ref2.placeholder,
|
|
76
|
+
buttonText = _ref2.buttonText,
|
|
77
|
+
lookupHandler = _ref2.lookupHandler,
|
|
78
|
+
mapOptionToString = _ref2.mapOptionToString,
|
|
79
|
+
_onSelect = _ref2.onSelect,
|
|
80
|
+
noResultsMessage = _ref2.noResultsMessage,
|
|
81
|
+
dropdownInstruction = _ref2.dropdownInstruction,
|
|
82
|
+
rest = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
|
|
83
|
+
|
|
84
|
+
var _useState = (0, _react.useState)(''),
|
|
85
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
86
|
+
query = _useState2[0],
|
|
87
|
+
setQuery = _useState2[1];
|
|
88
|
+
|
|
89
|
+
var _useState3 = (0, _react.useState)(''),
|
|
90
|
+
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
|
|
91
|
+
errorMessage = _useState4[0],
|
|
92
|
+
setErrorMessage = _useState4[1];
|
|
93
|
+
|
|
94
|
+
var _useState5 = (0, _react.useState)([]),
|
|
95
|
+
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
|
|
96
|
+
options = _useState6[0],
|
|
97
|
+
setOptions = _useState6[1];
|
|
98
|
+
|
|
99
|
+
var _useState7 = (0, _react.useState)(false),
|
|
100
|
+
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
|
|
101
|
+
isSearching = _useState8[0],
|
|
102
|
+
setIsSearching = _useState8[1];
|
|
103
|
+
|
|
104
|
+
var handler = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
|
|
105
|
+
var results;
|
|
106
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
107
|
+
while (1) {
|
|
108
|
+
switch (_context.prev = _context.next) {
|
|
109
|
+
case 0:
|
|
110
|
+
setErrorMessage('');
|
|
111
|
+
setIsSearching(true);
|
|
112
|
+
_context.prev = 2;
|
|
113
|
+
_context.next = 5;
|
|
114
|
+
return lookupHandler(query);
|
|
115
|
+
|
|
116
|
+
case 5:
|
|
117
|
+
results = _context.sent;
|
|
118
|
+
setOptions(results);
|
|
119
|
+
|
|
120
|
+
if (results.length === 0) {
|
|
121
|
+
setErrorMessage(noResultsMessage);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_context.next = 13;
|
|
125
|
+
break;
|
|
126
|
+
|
|
127
|
+
case 10:
|
|
128
|
+
_context.prev = 10;
|
|
129
|
+
_context.t0 = _context["catch"](2);
|
|
130
|
+
setErrorMessage(_context.t0.message);
|
|
131
|
+
|
|
132
|
+
case 13:
|
|
133
|
+
setIsSearching(false);
|
|
134
|
+
|
|
135
|
+
case 14:
|
|
136
|
+
case "end":
|
|
137
|
+
return _context.stop();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}, _callee, null, [[2, 10]]);
|
|
141
|
+
})), [query, setOptions, setErrorMessage, noResultsMessage, lookupHandler]);
|
|
142
|
+
return /*#__PURE__*/_react.default.createElement("div", rest, /*#__PURE__*/_react.default.createElement(_StyledTextInputWithDropdown, {
|
|
143
|
+
name: name,
|
|
144
|
+
id: name,
|
|
145
|
+
value: query,
|
|
146
|
+
options: options.map(mapOptionToString),
|
|
147
|
+
label: label,
|
|
148
|
+
placeholder: placeholder,
|
|
149
|
+
onChange: function onChange(e) {
|
|
150
|
+
setQuery(e.target.value);
|
|
151
|
+
setErrorMessage('');
|
|
152
|
+
setOptions([]);
|
|
153
|
+
},
|
|
154
|
+
onKeyPress: function onKeyPress(e) {
|
|
155
|
+
var keyCode = e.keyCode || e.which;
|
|
156
|
+
|
|
157
|
+
if (keyCode === KEY_CODE_ENTER) {
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
return handler();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return null;
|
|
163
|
+
},
|
|
164
|
+
onSelect: function onSelect(text, index) {
|
|
165
|
+
var selection = options[index];
|
|
166
|
+
|
|
167
|
+
_onSelect(selection);
|
|
168
|
+
|
|
169
|
+
setQuery('');
|
|
170
|
+
setErrorMessage('');
|
|
171
|
+
setOptions([]);
|
|
172
|
+
},
|
|
173
|
+
errorMsg: errorMessage,
|
|
174
|
+
dropdownInstruction: dropdownInstruction,
|
|
175
|
+
$_css: (0, _spacing.default)('md')
|
|
176
|
+
}), /*#__PURE__*/_react.default.createElement(StyledButton, {
|
|
177
|
+
type: "button",
|
|
178
|
+
onClick: function onClick() {
|
|
179
|
+
return handler();
|
|
180
|
+
},
|
|
181
|
+
loading: isSearching,
|
|
182
|
+
disabled: isSearching,
|
|
183
|
+
loadingText: "Searching"
|
|
184
|
+
}, buttonText));
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
Lookup.defaultProps = {
|
|
188
|
+
noResultsMessage: 'Sorry, could not find any results for your search',
|
|
189
|
+
dropdownInstruction: ''
|
|
190
|
+
};
|
|
191
|
+
var _default = Lookup;
|
|
192
|
+
exports.default = _default;
|
|
193
|
+
|
|
194
|
+
var _StyledTextInputWithDropdown = (0, _styledComponents.default)(_TextInputWithDropdown.default).withConfig({
|
|
195
|
+
displayName: "Lookup___StyledTextInputWithDropdown",
|
|
196
|
+
componentId: "sc-uu5bpv-1"
|
|
197
|
+
})(function (p) {
|
|
198
|
+
return {
|
|
199
|
+
marginBottom: p.$_css
|
|
200
|
+
};
|
|
201
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
|
|
10
|
+
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/objectWithoutProperties"));
|
|
11
|
+
|
|
12
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
13
|
+
|
|
14
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/esm/asyncToGenerator"));
|
|
15
|
+
|
|
16
|
+
var _react = _interopRequireDefault(require("react"));
|
|
17
|
+
|
|
18
|
+
var _axios = _interopRequireDefault(require("axios"));
|
|
19
|
+
|
|
20
|
+
var _Lookup = _interopRequireDefault(require("../Lookup/Lookup"));
|
|
21
|
+
|
|
22
|
+
var _excluded = ["onSelect"];
|
|
23
|
+
|
|
24
|
+
var schoolFetcher = /*#__PURE__*/function () {
|
|
25
|
+
var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(query) {
|
|
26
|
+
var res;
|
|
27
|
+
return _regenerator.default.wrap(function _callee$(_context) {
|
|
28
|
+
while (1) {
|
|
29
|
+
switch (_context.prev = _context.next) {
|
|
30
|
+
case 0:
|
|
31
|
+
if (!(!query || !query.trim())) {
|
|
32
|
+
_context.next = 2;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
throw new Error('Please enter a search query');
|
|
37
|
+
|
|
38
|
+
case 2:
|
|
39
|
+
if (!(query.length < 2)) {
|
|
40
|
+
_context.next = 4;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw new Error('Please enter at least two characters');
|
|
45
|
+
|
|
46
|
+
case 4:
|
|
47
|
+
_context.prev = 4;
|
|
48
|
+
_context.next = 7;
|
|
49
|
+
return _axios.default.get('https://lookups.sls.comicrelief.com/schools/lookup', {
|
|
50
|
+
timeout: 10000,
|
|
51
|
+
params: {
|
|
52
|
+
query: query
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
case 7:
|
|
57
|
+
res = _context.sent;
|
|
58
|
+
return _context.abrupt("return", res.data.data.schools);
|
|
59
|
+
|
|
60
|
+
case 11:
|
|
61
|
+
_context.prev = 11;
|
|
62
|
+
_context.t0 = _context["catch"](4);
|
|
63
|
+
throw new Error('Sorry, something unexpected went wrong. Please try again or enter your school manually');
|
|
64
|
+
|
|
65
|
+
case 14:
|
|
66
|
+
case "end":
|
|
67
|
+
return _context.stop();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}, _callee, null, [[4, 11]]);
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
return function schoolFetcher(_x) {
|
|
74
|
+
return _ref.apply(this, arguments);
|
|
75
|
+
};
|
|
76
|
+
}();
|
|
77
|
+
|
|
78
|
+
var schoolToString = function schoolToString(school) {
|
|
79
|
+
return "".concat(school.name, ", ").concat(school.post_code);
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* The component library's school lookup component uses a typeahead/search-as-you-type approach.
|
|
83
|
+
*
|
|
84
|
+
* Given the API we use is v flaky and can be slow, this isn't really ideal.
|
|
85
|
+
*
|
|
86
|
+
* This version just has a simple input + a button (or you can hit enter) to trigger the search.
|
|
87
|
+
*
|
|
88
|
+
* @param onSelect
|
|
89
|
+
* @param rest
|
|
90
|
+
* @returns {JSX.Element}
|
|
91
|
+
* @constructor
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
var SimpleSchoolLookup = function SimpleSchoolLookup(_ref2) {
|
|
96
|
+
var onSelect = _ref2.onSelect,
|
|
97
|
+
rest = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
|
|
98
|
+
return /*#__PURE__*/_react.default.createElement(_Lookup.default, Object.assign({
|
|
99
|
+
name: "school_lookup",
|
|
100
|
+
label: "Enter the name or postcode of your organisation",
|
|
101
|
+
placeholder: "Enter name or postcode...",
|
|
102
|
+
buttonText: "Find school",
|
|
103
|
+
dropdownInstruction: "Please select an organisation from the list below",
|
|
104
|
+
noResultsMessage: "Sorry, could not find anything matching your search",
|
|
105
|
+
lookupHandler: schoolFetcher,
|
|
106
|
+
mapOptionToString: schoolToString,
|
|
107
|
+
onSelect: onSelect
|
|
108
|
+
}, rest));
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
var _default = SimpleSchoolLookup;
|
|
112
|
+
exports.default = _default;
|
|
@@ -896,6 +896,10 @@ exports[`renders Single Message with full width image and no text correctly 1`]
|
|
|
896
896
|
z-index: 1;
|
|
897
897
|
}
|
|
898
898
|
|
|
899
|
+
@media (min-width:740px) {
|
|
900
|
+
|
|
901
|
+
}
|
|
902
|
+
|
|
899
903
|
@media (min-width:740px) {
|
|
900
904
|
.c0 {
|
|
901
905
|
-webkit-flex-direction: row;
|
|
@@ -1010,6 +1014,10 @@ exports[`renders Single Message with no Image correctly 1`] = `
|
|
|
1010
1014
|
padding: 1rem;
|
|
1011
1015
|
}
|
|
1012
1016
|
|
|
1017
|
+
@media (min-width:740px) {
|
|
1018
|
+
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1013
1021
|
@media (min-width:740px) {
|
|
1014
1022
|
.c0 {
|
|
1015
1023
|
-webkit-flex-direction: row;
|
package/dist/index.js
CHANGED
|
@@ -167,6 +167,12 @@ Object.defineProperty(exports, "Label", {
|
|
|
167
167
|
return _Label.default;
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
|
+
Object.defineProperty(exports, "ButtonWithStates", {
|
|
171
|
+
enumerable: true,
|
|
172
|
+
get: function get() {
|
|
173
|
+
return _ButtonWithStates.default;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
170
176
|
Object.defineProperty(exports, "HeroBanner", {
|
|
171
177
|
enumerable: true,
|
|
172
178
|
get: function get() {
|
|
@@ -329,6 +335,18 @@ Object.defineProperty(exports, "Descriptor", {
|
|
|
329
335
|
return _Descriptor.default;
|
|
330
336
|
}
|
|
331
337
|
});
|
|
338
|
+
Object.defineProperty(exports, "Lookup", {
|
|
339
|
+
enumerable: true,
|
|
340
|
+
get: function get() {
|
|
341
|
+
return _Lookup.default;
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
Object.defineProperty(exports, "SimpleSchoolLookup", {
|
|
345
|
+
enumerable: true,
|
|
346
|
+
get: function get() {
|
|
347
|
+
return _SimpleSchoolLookup.default;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
332
350
|
Object.defineProperty(exports, "EmailSignUp", {
|
|
333
351
|
enumerable: true,
|
|
334
352
|
get: function get() {
|
|
@@ -416,6 +434,8 @@ var _ErrorText = _interopRequireDefault(require("./components/Atoms/ErrorText/Er
|
|
|
416
434
|
|
|
417
435
|
var _Label = _interopRequireDefault(require("./components/Atoms/Label/Label"));
|
|
418
436
|
|
|
437
|
+
var _ButtonWithStates = _interopRequireDefault(require("./components/Atoms/ButtonWithStates/ButtonWithStates"));
|
|
438
|
+
|
|
419
439
|
var _HeroBanner = _interopRequireDefault(require("./components/Molecules/HeroBanner/HeroBanner"));
|
|
420
440
|
|
|
421
441
|
var _InfoBanner = _interopRequireDefault(require("./components/Molecules/InfoBanner/InfoBanner"));
|
|
@@ -470,6 +490,10 @@ var _Chip = _interopRequireDefault(require("./components/Molecules/Chip/Chip"));
|
|
|
470
490
|
|
|
471
491
|
var _Descriptor = _interopRequireDefault(require("./components/Molecules/Descriptor/Descriptor"));
|
|
472
492
|
|
|
493
|
+
var _Lookup = _interopRequireDefault(require("./components/Molecules/Lookup/Lookup"));
|
|
494
|
+
|
|
495
|
+
var _SimpleSchoolLookup = _interopRequireDefault(require("./components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup"));
|
|
496
|
+
|
|
473
497
|
var _EmailSignUp = _interopRequireDefault(require("./components/Organisms/EmailSignUp/EmailSignUp"));
|
|
474
498
|
|
|
475
499
|
var _CookieBanner = _interopRequireDefault(require("./components/Organisms/CookieBanner/CookieBanner"));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@comicrelief/component-library",
|
|
3
3
|
"author": "Comic Relief Engineering Team",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.7.0",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"jest": {
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"react-hook-form": "^6.3.0",
|
|
36
36
|
"react-modal": "^3.14.3",
|
|
37
37
|
"react-scripts": "4.0.3",
|
|
38
|
+
"react-spinners": "^0.11.0",
|
|
38
39
|
"react-styleguidist": "^11.1.7",
|
|
39
40
|
"react-test-renderer": "^17.0.2",
|
|
40
41
|
"react-uid": "^2.2.0",
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled from 'styled-components';
|
|
4
|
+
import ScaleLoader from 'react-spinners/ScaleLoader';
|
|
5
|
+
import spacing from '../../../theme/shared/spacing';
|
|
6
|
+
import Button from '../Button/Button';
|
|
7
|
+
|
|
8
|
+
const ButtonWithDisabledState = styled(Button)`
|
|
9
|
+
&:disabled {
|
|
10
|
+
cursor: not-allowed;
|
|
11
|
+
opacity: 0.75;
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const LoaderContainer = styled.div`${({ withMargin }) => (withMargin ? `
|
|
16
|
+
margin-top: ${spacing('xsm')};
|
|
17
|
+
margin-left: ${spacing('md')};
|
|
18
|
+
` : '')}`;
|
|
19
|
+
|
|
20
|
+
// A button with loading and disabled states.
|
|
21
|
+
const ButtonWithStates = React.forwardRef(({
|
|
22
|
+
children, loadingText, loading, disabled, ...rest
|
|
23
|
+
}, ref) => {
|
|
24
|
+
const [loaderColour, setLoaderColour] = useState(null);
|
|
25
|
+
|
|
26
|
+
// Can't see a simpler way to get the button's text colour, without reading the value
|
|
27
|
+
// via JavaScript.
|
|
28
|
+
// (e.g. the `theme.buttonColours` helper returns a CSS string split into an array -
|
|
29
|
+
// don't really want to be parsing that.)
|
|
30
|
+
// (And can't use inherit because ScaleLoader's color prop is actually setting its
|
|
31
|
+
// background color.)
|
|
32
|
+
const getLoaderColour = useCallback(node => {
|
|
33
|
+
if (node && typeof window.getComputedStyle === 'function') {
|
|
34
|
+
const textColour = window.getComputedStyle(node).color;
|
|
35
|
+
if (textColour) {
|
|
36
|
+
setLoaderColour(textColour);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<ButtonWithDisabledState ref={ref} disabled={disabled} {...rest}>
|
|
43
|
+
{loading ? loadingText : children}
|
|
44
|
+
<LoaderContainer ref={getLoaderColour} withMargin={loading}>
|
|
45
|
+
<ScaleLoader height={16} width={2} loading={loading} color={loaderColour} />
|
|
46
|
+
</LoaderContainer>
|
|
47
|
+
</ButtonWithDisabledState>
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
ButtonWithStates.propTypes = {
|
|
52
|
+
children: PropTypes.node.isRequired,
|
|
53
|
+
loadingText: PropTypes.string,
|
|
54
|
+
loading: PropTypes.bool,
|
|
55
|
+
disabled: PropTypes.bool
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
ButtonWithStates.defaultProps = {
|
|
59
|
+
loading: false,
|
|
60
|
+
disabled: false,
|
|
61
|
+
loadingText: 'Loading'
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default ButtonWithStates;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
|
|
4
4
|
import StyledLink, { HelperText, IconWrapper } from './Link.style';
|
|
@@ -19,13 +19,14 @@ const Link = ({
|
|
|
19
19
|
iconFirst,
|
|
20
20
|
...rest
|
|
21
21
|
}) => {
|
|
22
|
+
const [documentHost, setDocumentHost] = useState('');
|
|
22
23
|
/**
|
|
23
24
|
* If we haven't specifically set the target via props, check if
|
|
24
25
|
* this is an internal link OR on our whitelist before making it a '_self' link
|
|
25
26
|
*/
|
|
26
27
|
if (target === null) {
|
|
27
28
|
// Use our helper function to determine the raw domains to compare
|
|
28
|
-
const currentDomain = getDomain(
|
|
29
|
+
const currentDomain = getDomain(documentHost);
|
|
29
30
|
const linkDomain = getDomain(href);
|
|
30
31
|
|
|
31
32
|
// Additional check for applications that need more control
|
|
@@ -45,6 +46,10 @@ const Link = ({
|
|
|
45
46
|
}
|
|
46
47
|
const hasIcon = icon !== null;
|
|
47
48
|
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
setDocumentHost(document.location.host);
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
48
53
|
return (
|
|
49
54
|
<StyledLink
|
|
50
55
|
{...rest}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import styled, { css } from 'styled-components';
|
|
4
|
+
import TextInputWithDropdown from '../../Atoms/TextInputWithDropdown/TextInputWithDropdown';
|
|
5
|
+
import spacing from '../../../theme/shared/spacing';
|
|
6
|
+
import ButtonWithStates from '../../Atoms/ButtonWithStates/ButtonWithStates';
|
|
7
|
+
|
|
8
|
+
const StyledButton = styled(ButtonWithStates)`${({ theme }) => css`
|
|
9
|
+
color: ${theme.color('grey_dark')};
|
|
10
|
+
border: 2px solid ${theme.color('grey_dark')};
|
|
11
|
+
background-color: ${theme.color('white')};
|
|
12
|
+
padding-left: ${spacing('lg')};
|
|
13
|
+
padding-right: ${spacing('lg')};
|
|
14
|
+
|
|
15
|
+
&:hover {
|
|
16
|
+
color: ${theme.color('grey_dark')};
|
|
17
|
+
background-color: ${theme.color('white')};
|
|
18
|
+
}
|
|
19
|
+
`}`;
|
|
20
|
+
|
|
21
|
+
const KEY_CODE_ENTER = 13;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A simple lookup component
|
|
25
|
+
*
|
|
26
|
+
* The `lookupHandler` should be an async function which is called when a lookup is triggered
|
|
27
|
+
* (either by hitting enter or clicking the button)
|
|
28
|
+
*
|
|
29
|
+
* It will receive the current search term and should:
|
|
30
|
+
* - take care of any validation on the search term
|
|
31
|
+
* - perform the actual lookup request
|
|
32
|
+
* - return an array of options (or an empty array if none were found)
|
|
33
|
+
* - only throw errors with user-friendly messages
|
|
34
|
+
*
|
|
35
|
+
* Any errors thrown will be caught and the message will be displayed to the user.
|
|
36
|
+
*
|
|
37
|
+
* The `onSelect` function will receive the chosen option.
|
|
38
|
+
*
|
|
39
|
+
* @param name
|
|
40
|
+
* @param label
|
|
41
|
+
* @param placeholder
|
|
42
|
+
* @param buttonText
|
|
43
|
+
* @param lookupHandler
|
|
44
|
+
* @param mapOptionToString
|
|
45
|
+
* @param onSelect
|
|
46
|
+
* @param noResultsMessage
|
|
47
|
+
* @param dropdownInstruction
|
|
48
|
+
* @param rest
|
|
49
|
+
* @returns {JSX.Element}
|
|
50
|
+
* @constructor
|
|
51
|
+
*/
|
|
52
|
+
const Lookup = ({
|
|
53
|
+
name,
|
|
54
|
+
label,
|
|
55
|
+
placeholder,
|
|
56
|
+
buttonText,
|
|
57
|
+
lookupHandler,
|
|
58
|
+
mapOptionToString,
|
|
59
|
+
onSelect,
|
|
60
|
+
noResultsMessage,
|
|
61
|
+
dropdownInstruction,
|
|
62
|
+
...rest
|
|
63
|
+
}) => {
|
|
64
|
+
const [query, setQuery] = useState('');
|
|
65
|
+
const [errorMessage, setErrorMessage] = useState('');
|
|
66
|
+
const [options, setOptions] = useState([]);
|
|
67
|
+
const [isSearching, setIsSearching] = useState(false);
|
|
68
|
+
|
|
69
|
+
const handler = useCallback(async () => {
|
|
70
|
+
setErrorMessage('');
|
|
71
|
+
setIsSearching(true);
|
|
72
|
+
try {
|
|
73
|
+
// If lookupHandler throws an error, the message will be displayed to the user
|
|
74
|
+
const results = await lookupHandler(query);
|
|
75
|
+
setOptions(results);
|
|
76
|
+
if (results.length === 0) {
|
|
77
|
+
setErrorMessage(noResultsMessage);
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
setErrorMessage(error.message);
|
|
81
|
+
}
|
|
82
|
+
setIsSearching(false);
|
|
83
|
+
}, [query, setOptions, setErrorMessage, noResultsMessage, lookupHandler]);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div {...rest}>
|
|
87
|
+
<TextInputWithDropdown
|
|
88
|
+
css={{ marginBottom: spacing('md') }}
|
|
89
|
+
name={name}
|
|
90
|
+
id={name}
|
|
91
|
+
value={query}
|
|
92
|
+
options={options.map(mapOptionToString)}
|
|
93
|
+
label={label}
|
|
94
|
+
placeholder={placeholder}
|
|
95
|
+
onChange={e => {
|
|
96
|
+
setQuery(e.target.value);
|
|
97
|
+
setErrorMessage('');
|
|
98
|
+
setOptions([]);
|
|
99
|
+
}}
|
|
100
|
+
onKeyPress={e => {
|
|
101
|
+
const keyCode = e.keyCode || e.which;
|
|
102
|
+
if (keyCode === KEY_CODE_ENTER) {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
return handler();
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}}
|
|
108
|
+
onSelect={(text, index) => {
|
|
109
|
+
const selection = options[index];
|
|
110
|
+
onSelect(selection);
|
|
111
|
+
setQuery('');
|
|
112
|
+
setErrorMessage('');
|
|
113
|
+
setOptions([]);
|
|
114
|
+
}}
|
|
115
|
+
errorMsg={errorMessage}
|
|
116
|
+
dropdownInstruction={dropdownInstruction}
|
|
117
|
+
/>
|
|
118
|
+
<StyledButton
|
|
119
|
+
type="button"
|
|
120
|
+
onClick={() => handler()}
|
|
121
|
+
loading={isSearching}
|
|
122
|
+
disabled={isSearching}
|
|
123
|
+
loadingText="Searching"
|
|
124
|
+
>
|
|
125
|
+
{buttonText}
|
|
126
|
+
</StyledButton>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
Lookup.propTypes = {
|
|
132
|
+
name: PropTypes.string.isRequired,
|
|
133
|
+
label: PropTypes.string.isRequired,
|
|
134
|
+
placeholder: PropTypes.string.isRequired,
|
|
135
|
+
buttonText: PropTypes.string.isRequired,
|
|
136
|
+
lookupHandler: PropTypes.func.isRequired,
|
|
137
|
+
mapOptionToString: PropTypes.func.isRequired,
|
|
138
|
+
onSelect: PropTypes.func.isRequired,
|
|
139
|
+
noResultsMessage: PropTypes.string,
|
|
140
|
+
dropdownInstruction: PropTypes.string
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
Lookup.defaultProps = {
|
|
144
|
+
noResultsMessage: 'Sorry, could not find any results for your search',
|
|
145
|
+
dropdownInstruction: ''
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export default Lookup;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import axios from 'axios';
|
|
4
|
+
|
|
5
|
+
import Lookup from '../Lookup/Lookup';
|
|
6
|
+
|
|
7
|
+
const schoolFetcher = async query => {
|
|
8
|
+
if (!query || !query.trim()) {
|
|
9
|
+
throw new Error('Please enter a search query');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (query.length < 2) {
|
|
13
|
+
throw new Error('Please enter at least two characters');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const res = await axios.get(
|
|
18
|
+
'https://lookups.sls.comicrelief.com/schools/lookup',
|
|
19
|
+
{ timeout: 10000, params: { query } }
|
|
20
|
+
);
|
|
21
|
+
return res.data.data.schools;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// if (typeof Sentry !== 'undefined') {
|
|
24
|
+
// Sentry.captureException(error);
|
|
25
|
+
// }
|
|
26
|
+
throw new Error('Sorry, something unexpected went wrong. Please try again or enter your school manually');
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const schoolToString = school => `${school.name}, ${school.post_code}`;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The component library's school lookup component uses a typeahead/search-as-you-type approach.
|
|
34
|
+
*
|
|
35
|
+
* Given the API we use is v flaky and can be slow, this isn't really ideal.
|
|
36
|
+
*
|
|
37
|
+
* This version just has a simple input + a button (or you can hit enter) to trigger the search.
|
|
38
|
+
*
|
|
39
|
+
* @param onSelect
|
|
40
|
+
* @param rest
|
|
41
|
+
* @returns {JSX.Element}
|
|
42
|
+
* @constructor
|
|
43
|
+
*/
|
|
44
|
+
const SimpleSchoolLookup = ({ onSelect, ...rest }) => (
|
|
45
|
+
<Lookup
|
|
46
|
+
name="school_lookup"
|
|
47
|
+
label="Enter the name or postcode of your organisation"
|
|
48
|
+
placeholder="Enter name or postcode..."
|
|
49
|
+
buttonText="Find school"
|
|
50
|
+
dropdownInstruction="Please select an organisation from the list below"
|
|
51
|
+
noResultsMessage="Sorry, could not find anything matching your search"
|
|
52
|
+
lookupHandler={schoolFetcher}
|
|
53
|
+
mapOptionToString={schoolToString}
|
|
54
|
+
onSelect={onSelect}
|
|
55
|
+
{...rest}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
SimpleSchoolLookup.propTypes = {
|
|
60
|
+
onSelect: PropTypes.func.isRequired
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default SimpleSchoolLookup;
|
|
@@ -896,6 +896,10 @@ exports[`renders Single Message with full width image and no text correctly 1`]
|
|
|
896
896
|
z-index: 1;
|
|
897
897
|
}
|
|
898
898
|
|
|
899
|
+
@media (min-width:740px) {
|
|
900
|
+
|
|
901
|
+
}
|
|
902
|
+
|
|
899
903
|
@media (min-width:740px) {
|
|
900
904
|
.c0 {
|
|
901
905
|
-webkit-flex-direction: row;
|
|
@@ -1010,6 +1014,10 @@ exports[`renders Single Message with no Image correctly 1`] = `
|
|
|
1010
1014
|
padding: 1rem;
|
|
1011
1015
|
}
|
|
1012
1016
|
|
|
1017
|
+
@media (min-width:740px) {
|
|
1018
|
+
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1013
1021
|
@media (min-width:740px) {
|
|
1014
1022
|
.c0 {
|
|
1015
1023
|
-webkit-flex-direction: row;
|
package/src/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export { default as SocialIcons } from './components/Atoms/SocialIcons/SocialIco
|
|
|
29
29
|
export { default as TextInputWithDropdown } from './components/Atoms/TextInputWithDropdown/TextInputWithDropdown';
|
|
30
30
|
export { default as ErrorText } from './components/Atoms/ErrorText/ErrorText';
|
|
31
31
|
export { default as Label } from './components/Atoms/Label/Label';
|
|
32
|
+
export { default as ButtonWithStates } from './components/Atoms/ButtonWithStates/ButtonWithStates';
|
|
32
33
|
|
|
33
34
|
/* Molecules */
|
|
34
35
|
export { default as HeroBanner } from './components/Molecules/HeroBanner/HeroBanner';
|
|
@@ -58,6 +59,8 @@ export { default as Countdown } from './components/Molecules/Countdown/Countdown
|
|
|
58
59
|
export { default as Banner } from './components/Molecules/Banner/Banner';
|
|
59
60
|
export { default as Chip } from './components/Molecules/Chip/Chip';
|
|
60
61
|
export { default as Descriptor } from './components/Molecules/Descriptor/Descriptor';
|
|
62
|
+
export { default as Lookup } from './components/Molecules/Lookup/Lookup';
|
|
63
|
+
export { default as SimpleSchoolLookup } from './components/Molecules/SimpleSchoolLookup/SimpleSchoolLookup';
|
|
61
64
|
|
|
62
65
|
/* Organisms */
|
|
63
66
|
export { default as EmailSignUp } from './components/Organisms/EmailSignUp/EmailSignUp';
|