<div class="search-field ">
<div class="search-field__field">
<input type="search" class="search-field__input" />
<button class="search-field__submit" type="submit"></button>
</div>
</div>
<div class="search-field {{ getmodifiers modifiers "search-field" }}">
<div class="search-field__field">
<input type="search" class="search-field__input" {{{getattributes attributes}}} />
<button class="search-field__submit" type="submit"></button>
</div>
</div>
/* No context defined. */
import React from 'react';
const Geolocation = (props) => {
const requestIpLocation = async (cb) => {
try {
const res = await fetch('https://ipinfo.io/geo');
const data = await res.json();
cb(data.loc.split(','));
} catch (e) {
console.warn(e);
}
};
const requestGeolocation = async (e) => {
e.preventDefault();
if (!navigator.geolocation) {
return requestIpLocation();
}
const cords = await new Promise((resolve) => {
navigator.geolocation.getCurrentPosition((position) => {
resolve([position.coords.latitude, position.coords.longitude]);
}, () => requestIpLocation(resolve));
});
props.onGeolocation(cords);
};
return (
<button
className="search-field__geolocation"
onClick={requestGeolocation}
/>
);
};
export default Geolocation;
import React from 'react';
import Downshift from 'downshift';
import PropTypes from 'prop-types';
import Icon from '../icon';
const SearchField = (props) => {
const {
preSelectedFirstItem,
onInputChange,
onSubmit,
onChange,
itemStyle,
items,
itemComponent,
className,
inputPlaceholder,
seeMoreLink,
seeMoreText
} = props;
function stateReducer(state, changes) {
// this prevents the menu from being closed when the user
// selects an item with a keyboard or mouse
switch (changes.type) {
case Downshift.stateChangeTypes.blurInput:
return {
...changes,
...(items[state.highlightedIndex] && { inputValue: items[state.highlightedIndex].value }),
...(typeof onSubmit !== 'undefined' && { inputValue: state.inputValue }),
...(onSubmit === 'undefined' && { highlightedIndex: state.highlightedIndex })
};
default:
return changes;
}
}
return (
<form onSubmit={(e) => onSubmit && onSubmit(e)}>
<Downshift
itemToString={item => (item ? item.value : ``)}
defaultHighlightedIndex={preSelectedFirstItem ? 0 : null}
stateReducer={stateReducer}
{...props}
>
{({
getInputProps,
getItemProps,
getMenuProps,
isOpen,
inputValue,
highlightedIndex
}) => (
<div className={`search-field ${className}`}>
<div className="search-field__field">
<input
name="q"
className="search-field__input"
placeholder={inputPlaceholder}
type="search"
{...getInputProps({
onChange: e => onInputChange(e)
})}
/>
<button
className="search-field__submit"
type="submit"
onClick={(e) => {
if (typeof items[highlightedIndex] !== 'undefined') {
onChange(items[highlightedIndex]);
e.preventDefault();
} else if (typeof onSubmit === 'undefined') {
e.preventDefault();
}
}}
/>
{props.children}
</div>
{isOpen && inputValue.length > 0 && items.length > 0
? (
<React.Fragment>
<ul
className={`search-field__autocomplete ${isOpen &&
`search-field__autocomplete--is-open`}`}
{...getMenuProps()}
>
{items.map((item, index) => (
<li
className={`search-field__item ${highlightedIndex ===
index &&
`search-field__item--selected`} ${itemStyle}`}
{...getItemProps({
key: index,
index,
item
})}
>
{itemComponent(item)}
</li>
))}
{
seeMoreLink && seeMoreLink.length > 0 &&
<li className='search-field__item search-field__item--link-holder'>
<a className='search-field__item--link' href={`${seeMoreLink}?qp=${inputValue}`}>
<span>{seeMoreText}</span>
<Icon icon='chevron-right' additionalClasses="search-field__item--icon" />
</a>
</li>
}
</ul>
</React.Fragment>
) : null}
</div>
)}
</Downshift>
</form>
);
};
SearchField.propTypes = {
onInputChange: PropTypes.func,
onSubmit: PropTypes.func,
itemStyle: PropTypes.string,
items: PropTypes.array.isRequired,
itemComponent: PropTypes.func,
className: PropTypes.string,
inputPlaceholder: PropTypes.string,
preSelectedFirstItem: PropTypes.bool,
seeMoreLink: PropTypes.string
};
SearchField.defaultProps = {
onInputChange: () => {},
itemStyle: '',
className: '',
preSelectedFirstItem: true,
seeMoreLink: ''
};
export default SearchField;
import SearchField from './SearchField';
export { default as Geolocation } from './Geolocation';
export default SearchField;
$height-big: size(8);
$height-small: size(6);
.search-field {
width: 100%;
position: relative;
margin-bottom: size(4);
&--big {
@include breakpoint-classes {
@include breakpoint($s) {
.search-field__input, .search-field__submit, .search-field__geolocation {
height: $height-big;
}
.search-field__submit, .search-field__geolocation {
width: $height-big;
background-size: calc(100% - #{size(3)});
}
}
}
}
}
.search-field__field {
display: flex;
}
.search-field__input {
border: $color-gray-2 1px solid;
padding: size(2) size(3);
line-height: size(3);
height: $height-small;
display: flex;
flex: 1;
font-size: size(2.5);
border-radius: size(.5) 0 0 size(.5);
border-right: 0;
background: $color-white;
width: 100%;
@include placeholder {
color: $color-gray-3;
font-size: size(2.5);
opacity: 1;
}
&::-webkit-input-placeholder {
transform: translateY(0);
-webkit-transform: translateY(2px);
}
&::-webkit-search-decoration,
&::-webkit-search-cancel-button,
&::-webkit-search-results-button,
&::-webkit-search-results-decoration {
display: none;
}
}
// buttons
.search-field__geolocation, .search-field__submit {
width: $height-small;
height: $height-small;
min-width: auto;
}
.search-field__geolocation {
background: url(./img/icon-crosshair.svg) $color-gray-1 no-repeat center;
border-radius: size(.5);
background-size: calc(100% - #{size(2)});
margin-left: size(1);
@include breakpoint($m) {
margin-left: size(2);
}
}
.search-field__submit {
background: url(./img/icon-search.svg) no-repeat center;
border-radius: 0 size(.5) size(.5) 0;
background-size: calc(100% - #{size(2)});
background-color: $color-green-dark;
&:hover {
cursor: pointer;
}
@include color-theme {
background-color: $arg-theme-color;
}
}
.search-field__autocomplete {
position: absolute;
width: 100%;
border-radius: size(.5);
border: $color-gray-2 1px solid;
visibility: hidden;
list-style: none;
padding: 0;
margin: 0;
text-align: left;
top: 100%;
z-index: 1;
&--is-open {
visibility: visible;
}
}
.search-field__item {
border-bottom: 1px solid $color-gray-2;
background-color: $color-white;
display: flex;
align-items: center;
&:nth-child(odd) {
background-color: $color-gray-1;
}
&--selected {
background-color: $color-green-pale !important;
}
&--link-holder {
justify-content: center;
padding: size(2) size(3);
}
&--link {
color: $color-green;
display: inline-block;
vertical-align: top;
position: relative;
padding-right: size(2);
}
&--icon {
position: absolute;
top: 50%;
right: 0;
width: 16px;
height: 16px;
vertical-align: middle;
fill: currentColor;
transform: translateY(-50%);
}
}
.search-widget__spinner {
position: absolute;
top:50%;
transform: translateY(-50%);
right: 70px;
}
No notes defined.