@automattic/vip-design-system 0.24.0 → 0.25.1
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/build/system/NewForm/FormAutocomplete.css +166 -0
- package/build/system/NewForm/FormAutocomplete.js +205 -0
- package/build/system/NewForm/FormAutocomplete.stories.js +99 -0
- package/build/system/NewForm/FormAutocomplete.test.js +69 -0
- package/build/system/NewForm/index.js +5 -1
- package/build/system/ResourceList/ResourceList.js +1 -1
- package/package.json +6 -2
- package/src/system/NewForm/FormAutocomplete.css +166 -0
- package/src/system/NewForm/FormAutocomplete.js +186 -0
- package/src/system/NewForm/FormAutocomplete.stories.jsx +63 -0
- package/src/system/NewForm/FormAutocomplete.test.js +32 -0
- package/src/system/NewForm/FormSelect.stories.jsx +1 -1
- package/src/system/NewForm/index.js +3 -1
- package/test/fileMock.js +1 -0
- package/build/system/Form/MultiSelect.js +0 -38
- package/build/system/UsageChart/UsageChart.js +0 -60
- package/build/system/UsageChart/index.js +0 -7
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
.autocomplete__wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.autocomplete__hint,
|
|
6
|
+
.autocomplete__input {
|
|
7
|
+
-webkit-appearance: none;
|
|
8
|
+
border: 2px solid #0b0c0c;
|
|
9
|
+
border-radius: 0; /* Safari 10 on iOS adds implicit border rounding. */
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
-moz-box-sizing: border-box;
|
|
12
|
+
-webkit-box-sizing: border-box;
|
|
13
|
+
margin-bottom: 0; /* BUG: Safari 10 on macOS seems to add an implicit margin. */
|
|
14
|
+
width: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.autocomplete__input {
|
|
18
|
+
background-color: transparent;
|
|
19
|
+
position: relative;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.autocomplete__hint {
|
|
23
|
+
color: #b1b4b6;
|
|
24
|
+
position: absolute;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.autocomplete__input--default {
|
|
28
|
+
padding: 5px;
|
|
29
|
+
}
|
|
30
|
+
.autocomplete__input--focused {
|
|
31
|
+
outline: 3px solid #fd0;
|
|
32
|
+
outline-offset: 0;
|
|
33
|
+
box-shadow: inset 0 0 0 2px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.autocomplete__input--show-all-values {
|
|
37
|
+
padding: 5px 34px 5px 5px; /* Space for arrow. Other padding should match .autocomplete__input--default. */
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.autocomplete__dropdown-arrow-down {
|
|
42
|
+
z-index: -1;
|
|
43
|
+
display: inline-block;
|
|
44
|
+
position: absolute;
|
|
45
|
+
right: 8px;
|
|
46
|
+
width: 24px;
|
|
47
|
+
height: 24px;
|
|
48
|
+
top: 10px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.autocomplete__menu {
|
|
52
|
+
background-color: #fff;
|
|
53
|
+
border: 2px solid #0B0C0C;
|
|
54
|
+
border-top: 0;
|
|
55
|
+
color: #0B0C0C;
|
|
56
|
+
margin: 0;
|
|
57
|
+
max-height: 342px;
|
|
58
|
+
overflow-x: hidden;
|
|
59
|
+
padding: 0;
|
|
60
|
+
width: 100%;
|
|
61
|
+
width: calc(100% - 4px);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.autocomplete__menu--visible {
|
|
65
|
+
display: block;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.autocomplete__menu--hidden {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.autocomplete__menu--overlay {
|
|
73
|
+
box-shadow: rgba(0, 0, 0, 0.256863) 0px 2px 6px;
|
|
74
|
+
left: 0;
|
|
75
|
+
position: absolute;
|
|
76
|
+
top: 100%;
|
|
77
|
+
z-index: 100;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.autocomplete__menu--inline {
|
|
81
|
+
position: relative;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.autocomplete__option {
|
|
85
|
+
border-bottom: solid #b1b4b6;
|
|
86
|
+
border-width: 1px 0;
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
display: block;
|
|
89
|
+
position: relative;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.autocomplete__option > * {
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.autocomplete__option:first-of-type {
|
|
97
|
+
border-top-width: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.autocomplete__option:last-of-type {
|
|
101
|
+
border-bottom-width: 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.autocomplete__option--odd {
|
|
105
|
+
background-color: #FAFAFA;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.autocomplete__option--focused,
|
|
109
|
+
.autocomplete__option:hover {
|
|
110
|
+
background-color: #1d70b8;
|
|
111
|
+
border-color: #1d70b8;
|
|
112
|
+
color: white;
|
|
113
|
+
outline: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media (-ms-high-contrast: active), (forced-colors: active) {
|
|
117
|
+
.autocomplete__menu {
|
|
118
|
+
border-color: FieldText;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.autocomplete__option {
|
|
122
|
+
background-color: Field;
|
|
123
|
+
color: FieldText;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.autocomplete__option--focused,
|
|
127
|
+
.autocomplete__option:hover {
|
|
128
|
+
forced-color-adjust: none; /* prevent backplate from obscuring text */
|
|
129
|
+
background-color: Highlight;
|
|
130
|
+
border-color: Highlight;
|
|
131
|
+
color: HighlightText;
|
|
132
|
+
|
|
133
|
+
/* Prefer SelectedItem / SelectedItemText in browsers that support it */
|
|
134
|
+
background-color: SelectedItem;
|
|
135
|
+
border-color: SelectedItem;
|
|
136
|
+
color: SelectedItemText;
|
|
137
|
+
outline-color: SelectedItemText;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.autocomplete__option--no-results {
|
|
142
|
+
background-color: #FAFAFA;
|
|
143
|
+
color: #646b6f;
|
|
144
|
+
cursor: not-allowed;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.autocomplete__hint,
|
|
148
|
+
.autocomplete__input,
|
|
149
|
+
.autocomplete__option {
|
|
150
|
+
font-size: 16px;
|
|
151
|
+
line-height: 1.25;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.autocomplete__hint,
|
|
155
|
+
.autocomplete__option {
|
|
156
|
+
padding: 5px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@media (min-width: 641px) {
|
|
160
|
+
.autocomplete__hint,
|
|
161
|
+
.autocomplete__input,
|
|
162
|
+
.autocomplete__option {
|
|
163
|
+
font-size: 19px;
|
|
164
|
+
line-height: 1.31579;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
exports.__esModule = true;
|
|
6
|
+
exports.FormAutocomplete = void 0;
|
|
7
|
+
|
|
8
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
|
+
|
|
10
|
+
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
|
11
|
+
|
|
12
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
13
|
+
|
|
14
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
15
|
+
|
|
16
|
+
var _Label = require("../Form/Label");
|
|
17
|
+
|
|
18
|
+
var _react2 = _interopRequireDefault(require("accessible-autocomplete/react"));
|
|
19
|
+
|
|
20
|
+
var _FormAutocomplete = _interopRequireDefault(require("./FormAutocomplete.css"));
|
|
21
|
+
|
|
22
|
+
exports.css = _FormAutocomplete["default"];
|
|
23
|
+
|
|
24
|
+
var _FormSelectContent = require("./FormSelectContent");
|
|
25
|
+
|
|
26
|
+
var _FormSelectArrow = require("./FormSelectArrow");
|
|
27
|
+
|
|
28
|
+
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
29
|
+
|
|
30
|
+
var _excluded = ["isInline", "forLabel", "options", "label", "getOptionLabel", "getOptionValue", "onChange", "value", "showAllValues", "displayMenu", "id"];
|
|
31
|
+
|
|
32
|
+
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); }
|
|
33
|
+
|
|
34
|
+
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; }
|
|
35
|
+
|
|
36
|
+
var defaultStyles = {
|
|
37
|
+
width: '100%',
|
|
38
|
+
py: 0,
|
|
39
|
+
borderWidth: '1px',
|
|
40
|
+
borderStyle: 'solid',
|
|
41
|
+
borderColor: 'border',
|
|
42
|
+
borderRadius: 1,
|
|
43
|
+
backgroundColor: 'background',
|
|
44
|
+
color: 'text',
|
|
45
|
+
minHeight: '36px',
|
|
46
|
+
lineHeight: '36px',
|
|
47
|
+
'&:focus': function focus(theme) {
|
|
48
|
+
return theme.outline;
|
|
49
|
+
},
|
|
50
|
+
'&:focus-visible': function focusVisible(theme) {
|
|
51
|
+
return theme.outline;
|
|
52
|
+
},
|
|
53
|
+
'&:focus-within': function focusWithin(theme) {
|
|
54
|
+
return theme.outline;
|
|
55
|
+
},
|
|
56
|
+
'&.autocomplete__input--focused': function autocomplete__inputFocused(theme) {
|
|
57
|
+
return theme.outline;
|
|
58
|
+
},
|
|
59
|
+
'& .autocomplete__input': {
|
|
60
|
+
width: '100%',
|
|
61
|
+
paddingLeft: 3,
|
|
62
|
+
py: 0,
|
|
63
|
+
borderWidth: 0,
|
|
64
|
+
color: 'text',
|
|
65
|
+
minHeight: '36px',
|
|
66
|
+
lineHeight: '36px',
|
|
67
|
+
'&:focus': {
|
|
68
|
+
outlineWidth: 0,
|
|
69
|
+
boxShadow: 'none'
|
|
70
|
+
},
|
|
71
|
+
'&:focus-visible': {
|
|
72
|
+
outlineWidth: 0,
|
|
73
|
+
boxShadow: 'none'
|
|
74
|
+
},
|
|
75
|
+
'&:focus-within': {
|
|
76
|
+
outlineWidth: 0,
|
|
77
|
+
boxShadow: 'none'
|
|
78
|
+
},
|
|
79
|
+
'&.autocomplete__input--focused': {
|
|
80
|
+
outlineWidth: 0,
|
|
81
|
+
boxShadow: 'none'
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
'& .autocomplete__menu': {
|
|
85
|
+
borderWidth: '1px',
|
|
86
|
+
borderStyle: 'solid',
|
|
87
|
+
borderColor: 'border',
|
|
88
|
+
borderRadius: 1,
|
|
89
|
+
backgroundColor: 'background',
|
|
90
|
+
color: 'text'
|
|
91
|
+
},
|
|
92
|
+
'& .autocomplete__hint, & .autocomplete__input, & .autocomplete__option': {
|
|
93
|
+
fontSize: 'inherit'
|
|
94
|
+
},
|
|
95
|
+
'& .autocomplete__wrapper': {
|
|
96
|
+
width: '100%',
|
|
97
|
+
paddingRight: '40px'
|
|
98
|
+
},
|
|
99
|
+
'& .autocomplete__input--show-all-values': {
|
|
100
|
+
paddingRight: 0
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var inlineStyles = {
|
|
104
|
+
borderWidth: 0
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
var FormAutocomplete = /*#__PURE__*/_react["default"].forwardRef(function (_ref, forwardRef) {
|
|
108
|
+
var isInline = _ref.isInline,
|
|
109
|
+
forLabel = _ref.forLabel,
|
|
110
|
+
options = _ref.options,
|
|
111
|
+
label = _ref.label,
|
|
112
|
+
getOptionLabel = _ref.getOptionLabel,
|
|
113
|
+
getOptionValue = _ref.getOptionValue,
|
|
114
|
+
_ref$onChange = _ref.onChange,
|
|
115
|
+
onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange,
|
|
116
|
+
value = _ref.value,
|
|
117
|
+
_ref$showAllValues = _ref.showAllValues,
|
|
118
|
+
showAllValues = _ref$showAllValues === void 0 ? true : _ref$showAllValues,
|
|
119
|
+
_ref$displayMenu = _ref.displayMenu,
|
|
120
|
+
displayMenu = _ref$displayMenu === void 0 ? 'overlay' : _ref$displayMenu,
|
|
121
|
+
_ref$id = _ref.id,
|
|
122
|
+
id = _ref$id === void 0 ? 'vip-autocomplete' : _ref$id,
|
|
123
|
+
props = (0, _objectWithoutPropertiesLoose2["default"])(_ref, _excluded);
|
|
124
|
+
|
|
125
|
+
var SelectLabel = function SelectLabel() {
|
|
126
|
+
return (0, _jsxRuntime.jsx)(_Label.Label, {
|
|
127
|
+
htmlFor: forLabel || id,
|
|
128
|
+
children: label
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
var inlineLabel = !!(isInline && label);
|
|
133
|
+
var optionLabel = (0, _react.useCallback)(function (option) {
|
|
134
|
+
return getOptionLabel ? getOptionLabel(option) : option.label;
|
|
135
|
+
}, [getOptionLabel]);
|
|
136
|
+
var getAllOptions = (0, _react.useMemo)(function () {
|
|
137
|
+
return [].concat(options.filter(function (option) {
|
|
138
|
+
return !option.options;
|
|
139
|
+
}), options.filter(function (option) {
|
|
140
|
+
return option.options;
|
|
141
|
+
}).map(function (option) {
|
|
142
|
+
return option.options;
|
|
143
|
+
})).reduce(function (a, b) {
|
|
144
|
+
return a.concat(b);
|
|
145
|
+
}, []);
|
|
146
|
+
}, [options]);
|
|
147
|
+
var getOptionByLabel = (0, _react.useCallback)(function (inputValue) {
|
|
148
|
+
return getAllOptions.find(function (option) {
|
|
149
|
+
return "" + optionLabel(option) === "" + inputValue;
|
|
150
|
+
});
|
|
151
|
+
}, [getAllOptions, optionLabel]);
|
|
152
|
+
var onValueChange = (0, _react.useCallback)(function (inputValue) {
|
|
153
|
+
if (inputValue) {
|
|
154
|
+
onChange(getOptionByLabel(inputValue), inputValue);
|
|
155
|
+
}
|
|
156
|
+
}, [onChange, getOptionByLabel]);
|
|
157
|
+
var suggest = (0, _react.useCallback)(function (query, populateResults) {
|
|
158
|
+
var data = options.filter(function (option) {
|
|
159
|
+
return optionLabel(option).toLowerCase().indexOf(query.toLowerCase()) >= 0;
|
|
160
|
+
});
|
|
161
|
+
populateResults(data.map(function (option) {
|
|
162
|
+
return optionLabel(option);
|
|
163
|
+
}));
|
|
164
|
+
}, [options]);
|
|
165
|
+
(0, _react.useEffect)(function () {
|
|
166
|
+
global.document.querySelector('.autocomplete__input').setAttribute('aria-activedescendant', '');
|
|
167
|
+
}, []);
|
|
168
|
+
(0, _react.useEffect)(function () {
|
|
169
|
+
global.document.querySelector('.autocomplete__menu').setAttribute('aria-label', label + " list");
|
|
170
|
+
}, [label]);
|
|
171
|
+
return (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
172
|
+
children: [label && !isInline && (0, _jsxRuntime.jsx)(SelectLabel, {}), (0, _jsxRuntime.jsx)("div", {
|
|
173
|
+
sx: (0, _extends2["default"])({}, defaultStyles, isInline && inlineStyles),
|
|
174
|
+
children: (0, _jsxRuntime.jsxs)(_FormSelectContent.FormSelectContent, {
|
|
175
|
+
isInline: inlineLabel,
|
|
176
|
+
label: inlineLabel ? (0, _jsxRuntime.jsx)(SelectLabel, {}) : null,
|
|
177
|
+
children: [(0, _jsxRuntime.jsx)(_react2["default"], (0, _extends2["default"])({
|
|
178
|
+
id: id,
|
|
179
|
+
showAllValues: showAllValues,
|
|
180
|
+
ref: forwardRef,
|
|
181
|
+
source: suggest,
|
|
182
|
+
defaultValue: value,
|
|
183
|
+
displayMenu: displayMenu,
|
|
184
|
+
onConfirm: onValueChange
|
|
185
|
+
}, props)), (0, _jsxRuntime.jsx)(_FormSelectArrow.FormSelectArrow, {})]
|
|
186
|
+
})
|
|
187
|
+
})]
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
exports.FormAutocomplete = FormAutocomplete;
|
|
192
|
+
FormAutocomplete.propTypes = {
|
|
193
|
+
id: _propTypes["default"].string,
|
|
194
|
+
showAllValues: _propTypes["default"].bool,
|
|
195
|
+
isInline: _propTypes["default"].bool,
|
|
196
|
+
forLabel: _propTypes["default"].string,
|
|
197
|
+
value: _propTypes["default"].string,
|
|
198
|
+
displayMenu: _propTypes["default"].string,
|
|
199
|
+
label: _propTypes["default"].string,
|
|
200
|
+
options: _propTypes["default"].array,
|
|
201
|
+
getOptionLabel: _propTypes["default"].func,
|
|
202
|
+
getOptionValue: _propTypes["default"].func,
|
|
203
|
+
onChange: _propTypes["default"].func
|
|
204
|
+
};
|
|
205
|
+
FormAutocomplete.displayName = 'FormAutocomplete';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
exports.__esModule = true;
|
|
6
|
+
exports["default"] = exports.Inline = exports.Default = void 0;
|
|
7
|
+
|
|
8
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
|
+
|
|
10
|
+
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
|
11
|
+
|
|
12
|
+
var Form = _interopRequireWildcard(require("."));
|
|
13
|
+
|
|
14
|
+
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
15
|
+
|
|
16
|
+
var _excluded = ["label", "width"];
|
|
17
|
+
|
|
18
|
+
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); }
|
|
19
|
+
|
|
20
|
+
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; }
|
|
21
|
+
|
|
22
|
+
var _default = {
|
|
23
|
+
title: 'Form/Autocomplete',
|
|
24
|
+
argTypes: {
|
|
25
|
+
placeholder: {
|
|
26
|
+
type: {
|
|
27
|
+
name: 'string',
|
|
28
|
+
required: false
|
|
29
|
+
},
|
|
30
|
+
control: {
|
|
31
|
+
type: 'text'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
label: {
|
|
35
|
+
type: {
|
|
36
|
+
name: 'string',
|
|
37
|
+
required: false
|
|
38
|
+
},
|
|
39
|
+
control: {
|
|
40
|
+
type: 'text'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports["default"] = _default;
|
|
46
|
+
var options = [{
|
|
47
|
+
value: 'chocolate',
|
|
48
|
+
label: 'Chocolate'
|
|
49
|
+
}, {
|
|
50
|
+
value: 'strawberry',
|
|
51
|
+
label: 'Strawberry Chocolate Vanilla Chocolate Vanilla'
|
|
52
|
+
}, {
|
|
53
|
+
value: 'vanilla',
|
|
54
|
+
label: 'Vanilla'
|
|
55
|
+
}];
|
|
56
|
+
var args = {
|
|
57
|
+
label: 'Label',
|
|
58
|
+
options: options
|
|
59
|
+
}; // eslint-disable-next-line react/prop-types
|
|
60
|
+
|
|
61
|
+
var DefaultComponent = function DefaultComponent(_ref) {
|
|
62
|
+
var _ref$label = _ref.label,
|
|
63
|
+
label = _ref$label === void 0 ? 'Label' : _ref$label,
|
|
64
|
+
_ref$width = _ref.width,
|
|
65
|
+
width = _ref$width === void 0 ? 250 : _ref$width,
|
|
66
|
+
rest = (0, _objectWithoutPropertiesLoose2["default"])(_ref, _excluded);
|
|
67
|
+
return (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
68
|
+
children: (0, _jsxRuntime.jsx)(Form.Root, {
|
|
69
|
+
children: (0, _jsxRuntime.jsx)("div", {
|
|
70
|
+
sx: {
|
|
71
|
+
width: width
|
|
72
|
+
},
|
|
73
|
+
children: (0, _jsxRuntime.jsx)(Form.Autocomplete, (0, _extends2["default"])({
|
|
74
|
+
id: "form-autocomplete",
|
|
75
|
+
label: label
|
|
76
|
+
}, rest))
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
var Default = function Default() {
|
|
83
|
+
return (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
84
|
+
children: (0, _jsxRuntime.jsx)(DefaultComponent, (0, _extends2["default"])({}, args))
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
exports.Default = Default;
|
|
89
|
+
|
|
90
|
+
var Inline = function Inline() {
|
|
91
|
+
var customArgs = (0, _extends2["default"])({}, args, {
|
|
92
|
+
isInline: true
|
|
93
|
+
});
|
|
94
|
+
return (0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
95
|
+
children: (0, _jsxRuntime.jsx)(DefaultComponent, (0, _extends2["default"])({}, customArgs))
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
exports.Inline = Inline;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
|
|
5
|
+
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
6
|
+
|
|
7
|
+
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
8
|
+
|
|
9
|
+
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
10
|
+
|
|
11
|
+
var _react = require("@testing-library/react");
|
|
12
|
+
|
|
13
|
+
var _jestAxe = require("jest-axe");
|
|
14
|
+
|
|
15
|
+
var _FormAutocomplete = require("./FormAutocomplete");
|
|
16
|
+
|
|
17
|
+
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* External dependencies
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Internal dependencies
|
|
25
|
+
*/
|
|
26
|
+
var options = [{
|
|
27
|
+
value: 'chocolate',
|
|
28
|
+
label: 'Chocolate'
|
|
29
|
+
}, {
|
|
30
|
+
value: 'strawberry',
|
|
31
|
+
label: 'Strawberry Chocolate Vanilla Chocolate Vanilla'
|
|
32
|
+
}, {
|
|
33
|
+
value: 'vanilla',
|
|
34
|
+
label: 'Vanilla'
|
|
35
|
+
}];
|
|
36
|
+
var defaultProps = {
|
|
37
|
+
label: 'This is a label',
|
|
38
|
+
options: options
|
|
39
|
+
};
|
|
40
|
+
describe('<FormAutocomplete />', function () {
|
|
41
|
+
it('renders the FormAutocomplete component', /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
|
|
42
|
+
var _render, container;
|
|
43
|
+
|
|
44
|
+
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
45
|
+
while (1) {
|
|
46
|
+
switch (_context.prev = _context.next) {
|
|
47
|
+
case 0:
|
|
48
|
+
_render = (0, _react.render)((0, _jsxRuntime.jsx)(_FormAutocomplete.FormAutocomplete, (0, _extends2["default"])({
|
|
49
|
+
id: "my_desert_list"
|
|
50
|
+
}, defaultProps))), container = _render.container;
|
|
51
|
+
expect(_react.screen.getByLabelText(defaultProps.label)).toBeInTheDocument(); // Check for accessibility issues
|
|
52
|
+
|
|
53
|
+
_context.t0 = expect;
|
|
54
|
+
_context.next = 5;
|
|
55
|
+
return (0, _jestAxe.axe)(container);
|
|
56
|
+
|
|
57
|
+
case 5:
|
|
58
|
+
_context.t1 = _context.sent;
|
|
59
|
+
_context.next = 8;
|
|
60
|
+
return (0, _context.t0)(_context.t1).toHaveNoViolations();
|
|
61
|
+
|
|
62
|
+
case 8:
|
|
63
|
+
case "end":
|
|
64
|
+
return _context.stop();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}, _callee);
|
|
68
|
+
})));
|
|
69
|
+
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports["default"] = exports.Select = exports.Root = void 0;
|
|
4
|
+
exports["default"] = exports.Select = exports.Root = exports.Autocomplete = void 0;
|
|
5
5
|
|
|
6
6
|
var _FormSelect = require("./FormSelect");
|
|
7
7
|
|
|
8
|
+
var _FormAutocomplete = require("./FormAutocomplete");
|
|
9
|
+
|
|
8
10
|
var _Form = require("./Form");
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -12,6 +14,8 @@ var _Form = require("./Form");
|
|
|
12
14
|
*/
|
|
13
15
|
var Select = _FormSelect.FormSelect;
|
|
14
16
|
exports.Select = Select;
|
|
17
|
+
var Autocomplete = _FormAutocomplete.FormAutocomplete;
|
|
18
|
+
exports.Autocomplete = Autocomplete;
|
|
15
19
|
var Root = _Form.Form;
|
|
16
20
|
exports.Root = Root;
|
|
17
21
|
var _default = Root;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/vip-design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"main": "build/system/index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build-storybook": "build-storybook",
|
|
7
7
|
"prepare": "npm run build",
|
|
8
|
-
"build": "npm run theme-update && cross-env NODE_ENV=production babel src --out-dir build && npm run theme-builder-copy",
|
|
8
|
+
"build": "npm run theme-update && cross-env NODE_ENV=production babel src --out-dir build --copy-files && npm run theme-builder-copy",
|
|
9
9
|
"format": "prettier --write \"src/**/*.{js,ts,tsx,md,mdx,json}\"",
|
|
10
10
|
"format:check": "prettier --list-different -- \"src/system/**/*.{js,ts,tsx,md,mdx,json}\"",
|
|
11
11
|
"jest": "NODE_ENV=test jest --detectOpenHandles --env=jsdom",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"@radix-ui/react-tooltip": "^1.0.0",
|
|
30
30
|
"@radix-ui/react-visually-hidden": "^1.0.0",
|
|
31
31
|
"@storybook/addon-storysource": "^6.5.10",
|
|
32
|
+
"accessible-autocomplete": "^2.0.4",
|
|
32
33
|
"babel-loader": "^8.2.2",
|
|
33
34
|
"classnames": "^2.3.1",
|
|
34
35
|
"framer-motion": "^3.9.1",
|
|
@@ -71,6 +72,9 @@
|
|
|
71
72
|
],
|
|
72
73
|
"transform": {
|
|
73
74
|
"\\.[jt]sx?$": "babel-jest"
|
|
75
|
+
},
|
|
76
|
+
"moduleNameMapper": {
|
|
77
|
+
"\\.(css|less)$": "<rootDir>/test/fileMock.js"
|
|
74
78
|
}
|
|
75
79
|
},
|
|
76
80
|
"devDependencies": {
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
.autocomplete__wrapper {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.autocomplete__hint,
|
|
6
|
+
.autocomplete__input {
|
|
7
|
+
-webkit-appearance: none;
|
|
8
|
+
border: 2px solid #0b0c0c;
|
|
9
|
+
border-radius: 0; /* Safari 10 on iOS adds implicit border rounding. */
|
|
10
|
+
box-sizing: border-box;
|
|
11
|
+
-moz-box-sizing: border-box;
|
|
12
|
+
-webkit-box-sizing: border-box;
|
|
13
|
+
margin-bottom: 0; /* BUG: Safari 10 on macOS seems to add an implicit margin. */
|
|
14
|
+
width: 100%;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.autocomplete__input {
|
|
18
|
+
background-color: transparent;
|
|
19
|
+
position: relative;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.autocomplete__hint {
|
|
23
|
+
color: #b1b4b6;
|
|
24
|
+
position: absolute;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.autocomplete__input--default {
|
|
28
|
+
padding: 5px;
|
|
29
|
+
}
|
|
30
|
+
.autocomplete__input--focused {
|
|
31
|
+
outline: 3px solid #fd0;
|
|
32
|
+
outline-offset: 0;
|
|
33
|
+
box-shadow: inset 0 0 0 2px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.autocomplete__input--show-all-values {
|
|
37
|
+
padding: 5px 34px 5px 5px; /* Space for arrow. Other padding should match .autocomplete__input--default. */
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.autocomplete__dropdown-arrow-down {
|
|
42
|
+
z-index: -1;
|
|
43
|
+
display: inline-block;
|
|
44
|
+
position: absolute;
|
|
45
|
+
right: 8px;
|
|
46
|
+
width: 24px;
|
|
47
|
+
height: 24px;
|
|
48
|
+
top: 10px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.autocomplete__menu {
|
|
52
|
+
background-color: #fff;
|
|
53
|
+
border: 2px solid #0B0C0C;
|
|
54
|
+
border-top: 0;
|
|
55
|
+
color: #0B0C0C;
|
|
56
|
+
margin: 0;
|
|
57
|
+
max-height: 342px;
|
|
58
|
+
overflow-x: hidden;
|
|
59
|
+
padding: 0;
|
|
60
|
+
width: 100%;
|
|
61
|
+
width: calc(100% - 4px);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.autocomplete__menu--visible {
|
|
65
|
+
display: block;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.autocomplete__menu--hidden {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.autocomplete__menu--overlay {
|
|
73
|
+
box-shadow: rgba(0, 0, 0, 0.256863) 0px 2px 6px;
|
|
74
|
+
left: 0;
|
|
75
|
+
position: absolute;
|
|
76
|
+
top: 100%;
|
|
77
|
+
z-index: 100;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.autocomplete__menu--inline {
|
|
81
|
+
position: relative;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.autocomplete__option {
|
|
85
|
+
border-bottom: solid #b1b4b6;
|
|
86
|
+
border-width: 1px 0;
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
display: block;
|
|
89
|
+
position: relative;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.autocomplete__option > * {
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.autocomplete__option:first-of-type {
|
|
97
|
+
border-top-width: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.autocomplete__option:last-of-type {
|
|
101
|
+
border-bottom-width: 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.autocomplete__option--odd {
|
|
105
|
+
background-color: #FAFAFA;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.autocomplete__option--focused,
|
|
109
|
+
.autocomplete__option:hover {
|
|
110
|
+
background-color: #1d70b8;
|
|
111
|
+
border-color: #1d70b8;
|
|
112
|
+
color: white;
|
|
113
|
+
outline: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media (-ms-high-contrast: active), (forced-colors: active) {
|
|
117
|
+
.autocomplete__menu {
|
|
118
|
+
border-color: FieldText;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.autocomplete__option {
|
|
122
|
+
background-color: Field;
|
|
123
|
+
color: FieldText;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.autocomplete__option--focused,
|
|
127
|
+
.autocomplete__option:hover {
|
|
128
|
+
forced-color-adjust: none; /* prevent backplate from obscuring text */
|
|
129
|
+
background-color: Highlight;
|
|
130
|
+
border-color: Highlight;
|
|
131
|
+
color: HighlightText;
|
|
132
|
+
|
|
133
|
+
/* Prefer SelectedItem / SelectedItemText in browsers that support it */
|
|
134
|
+
background-color: SelectedItem;
|
|
135
|
+
border-color: SelectedItem;
|
|
136
|
+
color: SelectedItemText;
|
|
137
|
+
outline-color: SelectedItemText;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.autocomplete__option--no-results {
|
|
142
|
+
background-color: #FAFAFA;
|
|
143
|
+
color: #646b6f;
|
|
144
|
+
cursor: not-allowed;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.autocomplete__hint,
|
|
148
|
+
.autocomplete__input,
|
|
149
|
+
.autocomplete__option {
|
|
150
|
+
font-size: 16px;
|
|
151
|
+
line-height: 1.25;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.autocomplete__hint,
|
|
155
|
+
.autocomplete__option {
|
|
156
|
+
padding: 5px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@media (min-width: 641px) {
|
|
160
|
+
.autocomplete__hint,
|
|
161
|
+
.autocomplete__input,
|
|
162
|
+
.autocomplete__option {
|
|
163
|
+
font-size: 19px;
|
|
164
|
+
line-height: 1.31579;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* External dependencies
|
|
5
|
+
*/
|
|
6
|
+
import React, { useCallback, useEffect, useMemo } from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import { Label } from '../Form/Label';
|
|
9
|
+
import Autocomplete from 'accessible-autocomplete/react';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import css from './FormAutocomplete.css';
|
|
15
|
+
import { FormSelectContent } from './FormSelectContent';
|
|
16
|
+
import { FormSelectArrow } from './FormSelectArrow';
|
|
17
|
+
|
|
18
|
+
const defaultStyles = {
|
|
19
|
+
width: '100%',
|
|
20
|
+
py: 0,
|
|
21
|
+
borderWidth: '1px',
|
|
22
|
+
borderStyle: 'solid',
|
|
23
|
+
borderColor: 'border',
|
|
24
|
+
borderRadius: 1,
|
|
25
|
+
backgroundColor: 'background',
|
|
26
|
+
color: 'text',
|
|
27
|
+
minHeight: '36px',
|
|
28
|
+
lineHeight: '36px',
|
|
29
|
+
'&:focus': theme => theme.outline,
|
|
30
|
+
'&:focus-visible': theme => theme.outline,
|
|
31
|
+
'&:focus-within': theme => theme.outline,
|
|
32
|
+
'&.autocomplete__input--focused': theme => theme.outline,
|
|
33
|
+
'& .autocomplete__input': {
|
|
34
|
+
width: '100%',
|
|
35
|
+
paddingLeft: 3,
|
|
36
|
+
py: 0,
|
|
37
|
+
borderWidth: 0,
|
|
38
|
+
color: 'text',
|
|
39
|
+
minHeight: '36px',
|
|
40
|
+
lineHeight: '36px',
|
|
41
|
+
'&:focus': { outlineWidth: 0, boxShadow: 'none' },
|
|
42
|
+
'&:focus-visible': { outlineWidth: 0, boxShadow: 'none' },
|
|
43
|
+
'&:focus-within': { outlineWidth: 0, boxShadow: 'none' },
|
|
44
|
+
'&.autocomplete__input--focused': { outlineWidth: 0, boxShadow: 'none' },
|
|
45
|
+
},
|
|
46
|
+
'& .autocomplete__menu': {
|
|
47
|
+
borderWidth: '1px',
|
|
48
|
+
borderStyle: 'solid',
|
|
49
|
+
borderColor: 'border',
|
|
50
|
+
borderRadius: 1,
|
|
51
|
+
backgroundColor: 'background',
|
|
52
|
+
color: 'text',
|
|
53
|
+
},
|
|
54
|
+
'& .autocomplete__hint, & .autocomplete__input, & .autocomplete__option': {
|
|
55
|
+
fontSize: 'inherit',
|
|
56
|
+
},
|
|
57
|
+
'& .autocomplete__wrapper': {
|
|
58
|
+
width: '100%',
|
|
59
|
+
paddingRight: '40px',
|
|
60
|
+
},
|
|
61
|
+
'& .autocomplete__input--show-all-values': {
|
|
62
|
+
paddingRight: 0,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const inlineStyles = {
|
|
67
|
+
borderWidth: 0,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const FormAutocomplete = React.forwardRef(
|
|
71
|
+
(
|
|
72
|
+
{
|
|
73
|
+
isInline,
|
|
74
|
+
forLabel,
|
|
75
|
+
options,
|
|
76
|
+
label,
|
|
77
|
+
getOptionLabel,
|
|
78
|
+
getOptionValue,
|
|
79
|
+
onChange = () => {},
|
|
80
|
+
value,
|
|
81
|
+
showAllValues = true,
|
|
82
|
+
displayMenu = 'overlay',
|
|
83
|
+
id = 'vip-autocomplete',
|
|
84
|
+
...props
|
|
85
|
+
},
|
|
86
|
+
forwardRef
|
|
87
|
+
) => {
|
|
88
|
+
const SelectLabel = () => <Label htmlFor={ forLabel || id }>{ label }</Label>;
|
|
89
|
+
|
|
90
|
+
const inlineLabel = !! ( isInline && label );
|
|
91
|
+
|
|
92
|
+
const optionLabel = useCallback(
|
|
93
|
+
option => ( getOptionLabel ? getOptionLabel( option ) : option.label ),
|
|
94
|
+
[ getOptionLabel ]
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const getAllOptions = useMemo(
|
|
98
|
+
() =>
|
|
99
|
+
[
|
|
100
|
+
...options.filter( option => ! option.options ),
|
|
101
|
+
...options.filter( option => option.options ).map( option => option.options ),
|
|
102
|
+
].reduce( ( a, b ) => a.concat( b ), [] ),
|
|
103
|
+
[ options ]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const getOptionByLabel = useCallback(
|
|
107
|
+
inputValue =>
|
|
108
|
+
getAllOptions.find( option => `${ optionLabel( option ) }` === `${ inputValue }` ),
|
|
109
|
+
[ getAllOptions, optionLabel ]
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const onValueChange = useCallback(
|
|
113
|
+
inputValue => {
|
|
114
|
+
if ( inputValue ) {
|
|
115
|
+
onChange( getOptionByLabel( inputValue ), inputValue );
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
[ onChange, getOptionByLabel ]
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const suggest = useCallback(
|
|
122
|
+
( query, populateResults ) => {
|
|
123
|
+
const data = options.filter(
|
|
124
|
+
option => optionLabel( option ).toLowerCase().indexOf( query.toLowerCase() ) >= 0
|
|
125
|
+
);
|
|
126
|
+
populateResults( data.map( option => optionLabel( option ) ) );
|
|
127
|
+
},
|
|
128
|
+
[ options ]
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
useEffect( () => {
|
|
132
|
+
global.document
|
|
133
|
+
.querySelector( '.autocomplete__input' )
|
|
134
|
+
.setAttribute( 'aria-activedescendant', '' );
|
|
135
|
+
}, [] );
|
|
136
|
+
|
|
137
|
+
useEffect( () => {
|
|
138
|
+
global.document
|
|
139
|
+
.querySelector( '.autocomplete__menu' )
|
|
140
|
+
.setAttribute( 'aria-label', `${ label } list` );
|
|
141
|
+
}, [ label ] );
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<>
|
|
145
|
+
{ label && ! isInline && <SelectLabel /> }
|
|
146
|
+
|
|
147
|
+
<div sx={ { ...defaultStyles, ...( isInline && inlineStyles ) } }>
|
|
148
|
+
<FormSelectContent
|
|
149
|
+
isInline={ inlineLabel }
|
|
150
|
+
label={ inlineLabel ? <SelectLabel /> : null }
|
|
151
|
+
>
|
|
152
|
+
<Autocomplete
|
|
153
|
+
id={ id }
|
|
154
|
+
showAllValues={ showAllValues }
|
|
155
|
+
ref={ forwardRef }
|
|
156
|
+
source={ suggest }
|
|
157
|
+
defaultValue={ value }
|
|
158
|
+
displayMenu={ displayMenu }
|
|
159
|
+
onConfirm={ onValueChange }
|
|
160
|
+
{ ...props }
|
|
161
|
+
/>
|
|
162
|
+
<FormSelectArrow />
|
|
163
|
+
</FormSelectContent>
|
|
164
|
+
</div>
|
|
165
|
+
</>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
FormAutocomplete.propTypes = {
|
|
171
|
+
id: PropTypes.string,
|
|
172
|
+
showAllValues: PropTypes.bool,
|
|
173
|
+
isInline: PropTypes.bool,
|
|
174
|
+
forLabel: PropTypes.string,
|
|
175
|
+
value: PropTypes.string,
|
|
176
|
+
displayMenu: PropTypes.string,
|
|
177
|
+
label: PropTypes.string,
|
|
178
|
+
options: PropTypes.array,
|
|
179
|
+
getOptionLabel: PropTypes.func,
|
|
180
|
+
getOptionValue: PropTypes.func,
|
|
181
|
+
onChange: PropTypes.func,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
FormAutocomplete.displayName = 'FormAutocomplete';
|
|
185
|
+
|
|
186
|
+
export { FormAutocomplete, css };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Internal dependencies
|
|
5
|
+
*/
|
|
6
|
+
import * as Form from '.';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Form/Autocomplete',
|
|
10
|
+
argTypes: {
|
|
11
|
+
placeholder: {
|
|
12
|
+
type: { name: 'string', required: false },
|
|
13
|
+
control: { type: 'text' },
|
|
14
|
+
},
|
|
15
|
+
label: {
|
|
16
|
+
type: { name: 'string', required: false },
|
|
17
|
+
control: { type: 'text' },
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const options = [
|
|
23
|
+
{ value: 'chocolate', label: 'Chocolate' },
|
|
24
|
+
{ value: 'strawberry', label: 'Strawberry Chocolate Vanilla Chocolate Vanilla' },
|
|
25
|
+
{ value: 'vanilla', label: 'Vanilla' },
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const args = {
|
|
29
|
+
label: 'Label',
|
|
30
|
+
options,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line react/prop-types
|
|
34
|
+
const DefaultComponent = ( { label = 'Label', width = 250, ...rest } ) => (
|
|
35
|
+
<>
|
|
36
|
+
<Form.Root>
|
|
37
|
+
<div sx={ { width } }>
|
|
38
|
+
<Form.Autocomplete id="form-autocomplete" label={ label } { ...rest } />
|
|
39
|
+
</div>
|
|
40
|
+
</Form.Root>
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const Default = () => {
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<DefaultComponent { ...args } />
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const Inline = () => {
|
|
53
|
+
const customArgs = {
|
|
54
|
+
...args,
|
|
55
|
+
isInline: true,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
<DefaultComponent { ...customArgs } />
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
import { axe } from 'jest-axe';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { FormAutocomplete } from './FormAutocomplete';
|
|
11
|
+
|
|
12
|
+
const options = [
|
|
13
|
+
{ value: 'chocolate', label: 'Chocolate' },
|
|
14
|
+
{ value: 'strawberry', label: 'Strawberry Chocolate Vanilla Chocolate Vanilla' },
|
|
15
|
+
{ value: 'vanilla', label: 'Vanilla' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const defaultProps = {
|
|
19
|
+
label: 'This is a label',
|
|
20
|
+
options,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
describe( '<FormAutocomplete />', () => {
|
|
24
|
+
it( 'renders the FormAutocomplete component', async () => {
|
|
25
|
+
const { container } = render( <FormAutocomplete id="my_desert_list" { ...defaultProps } /> );
|
|
26
|
+
|
|
27
|
+
expect( screen.getByLabelText( defaultProps.label ) ).toBeInTheDocument();
|
|
28
|
+
|
|
29
|
+
// Check for accessibility issues
|
|
30
|
+
await expect( await axe( container ) ).toHaveNoViolations();
|
|
31
|
+
} );
|
|
32
|
+
} );
|
|
@@ -70,7 +70,7 @@ const DefaultComponent = ( { label = 'Label', width = 250, onChange, ...rest } )
|
|
|
70
70
|
export const Default = DefaultComponent.bind( {} );
|
|
71
71
|
Default.args = {
|
|
72
72
|
placeholder: '- Select -',
|
|
73
|
-
options
|
|
73
|
+
options,
|
|
74
74
|
};
|
|
75
75
|
|
|
76
76
|
export const WithGroup = DefaultComponent.bind( {} );
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { FormSelect } from './FormSelect';
|
|
6
|
+
import { FormAutocomplete } from './FormAutocomplete';
|
|
6
7
|
import { Form } from './Form';
|
|
7
8
|
|
|
8
9
|
const Select = FormSelect;
|
|
10
|
+
const Autocomplete = FormAutocomplete;
|
|
9
11
|
const Root = Form;
|
|
10
12
|
|
|
11
|
-
export { Root, Select };
|
|
13
|
+
export { Root, Select, Autocomplete };
|
|
12
14
|
|
|
13
15
|
export default Root;
|
package/test/fileMock.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = {};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true;
|
|
4
|
-
exports.MultiSelect = void 0;
|
|
5
|
-
|
|
6
|
-
var _reactSelect = _interopRequireDefault(require("react-select"));
|
|
7
|
-
|
|
8
|
-
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
9
|
-
|
|
10
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
11
|
-
|
|
12
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
13
|
-
|
|
14
|
-
var vipGold = '#c29c69'; // hardcoding for now
|
|
15
|
-
|
|
16
|
-
var vipGrey2 = '#d7dee2';
|
|
17
|
-
var customStyles = {
|
|
18
|
-
control: function control(styles) {
|
|
19
|
-
return _extends({}, styles, {
|
|
20
|
-
border: "1px solid " + vipGrey2,
|
|
21
|
-
boxShadow: 'none',
|
|
22
|
-
'&:hover': {
|
|
23
|
-
border: "1px solid " + vipGold
|
|
24
|
-
},
|
|
25
|
-
'&:focus': {
|
|
26
|
-
border: "1px solid " + vipGold
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
var MultiSelect = function MultiSelect(props) {
|
|
33
|
-
return (0, _jsxRuntime.jsx)(_reactSelect["default"], _extends({}, props, {
|
|
34
|
-
styles: customStyles
|
|
35
|
-
}));
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
exports.MultiSelect = MultiSelect;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
exports.__esModule = true;
|
|
4
|
-
exports.UsageChart = void 0;
|
|
5
|
-
|
|
6
|
-
var _framerMotion = require("framer-motion");
|
|
7
|
-
|
|
8
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
9
|
-
|
|
10
|
-
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
11
|
-
|
|
12
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* External dependencies
|
|
16
|
-
*/
|
|
17
|
-
var UsageChart = function UsageChart(_ref) {
|
|
18
|
-
var total = _ref.total,
|
|
19
|
-
max = _ref.max,
|
|
20
|
-
_ref$variant = _ref.variant,
|
|
21
|
-
variant = _ref$variant === void 0 ? 'primary' : _ref$variant;
|
|
22
|
-
var width = total / max * 100 + '%';
|
|
23
|
-
var formattedTotal = total;
|
|
24
|
-
|
|
25
|
-
if (total > 1000000) {
|
|
26
|
-
formattedTotal = (total / 1000000).toFixed(2) + "M";
|
|
27
|
-
} else if (total > 1000) {
|
|
28
|
-
formattedTotal = (total / 1000).toFixed(2) + "K";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return (0, _jsxRuntime.jsx)("div", {
|
|
32
|
-
sx: {
|
|
33
|
-
height: variant === 'primary' ? 32 : 8,
|
|
34
|
-
overflow: 'hidden',
|
|
35
|
-
backgroundColor: variant === 'primary' ? 'border' : 'transparent'
|
|
36
|
-
},
|
|
37
|
-
children: (0, _jsxRuntime.jsx)(_framerMotion.motion.div, {
|
|
38
|
-
initial: {
|
|
39
|
-
width: 0
|
|
40
|
-
},
|
|
41
|
-
animate: {
|
|
42
|
-
width: width
|
|
43
|
-
},
|
|
44
|
-
transition: {
|
|
45
|
-
duration: 0.7
|
|
46
|
-
},
|
|
47
|
-
sx: {
|
|
48
|
-
height: '100%',
|
|
49
|
-
backgroundColor: variant === 'primary' ? 'primary' : 'grey.40'
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
exports.UsageChart = UsageChart;
|
|
56
|
-
UsageChart.propTypes = {
|
|
57
|
-
total: _propTypes["default"].number,
|
|
58
|
-
max: _propTypes["default"].number,
|
|
59
|
-
variant: _propTypes["default"].string
|
|
60
|
-
};
|