@npm_leadtech/legal-lib-components 7.22.0 → 7.22.3
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/images/svg/close-grey-24px.svg +3 -0
- package/dist/src/components/atoms/DropdownInput/DropdownInput.d.ts +1 -1
- package/dist/src/components/atoms/DropdownInput/DropdownInput.js +5 -4
- package/dist/src/components/atoms/DropdownInput/DropdownInput.styled.js +38 -33
- package/dist/src/components/atoms/DropdownInput/DropdownInput.styled.ts +38 -34
- package/dist/src/components/atoms/DropdownInput/DropdownInput.tsx +49 -52
- package/dist/src/components/molecules/SearchBar/SearchBar.js +76 -26
- package/dist/src/components/molecules/SearchBar/SearchBar.styled.js +41 -43
- package/dist/src/components/molecules/SearchBar/SearchBar.styled.ts +41 -43
- package/dist/src/components/molecules/SearchBar/SearchBar.tsx +98 -47
- package/dist/src/hooks/useSearchFunction.d.ts +10 -0
- package/dist/src/hooks/useSearchFunction.js +28 -0
- package/dist/src/hooks/useSearchFunction.tsx +63 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -6,58 +6,56 @@ export const SearchBarStyled = styled.div`
|
|
|
6
6
|
.search {
|
|
7
7
|
width: calc(100% - 3rem);
|
|
8
8
|
margin: 0 1.5rem;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
@media ${device['landscape-tablets']} {
|
|
13
|
+
&.modal_searchbar {
|
|
14
|
+
position: fixed;
|
|
15
|
+
top: 0;
|
|
16
|
+
left: 0;
|
|
17
|
+
width: 100vw;
|
|
18
|
+
height: 100vh;
|
|
19
|
+
background: rgba(255, 255, 255, 0.95);
|
|
20
|
+
z-index: 9999;
|
|
21
|
+
display: flex;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
align-items: flex-start;
|
|
24
|
+
padding-top: 100px;
|
|
25
|
+
|
|
26
|
+
.modal_searchbar__content {
|
|
27
|
+
background-color: var(--neutral-white);
|
|
28
|
+
padding: 1.5rem;
|
|
29
|
+
border-radius: 8px;
|
|
30
|
+
width: 90%;
|
|
31
|
+
max-width: 768px;
|
|
32
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
33
|
+
|
|
34
|
+
@media ${device['landscape-tablets']} {
|
|
35
|
+
padding: 0;
|
|
36
|
+
border-radius: 8px 8px 0 0;
|
|
37
|
+
}
|
|
18
38
|
}
|
|
19
39
|
|
|
20
|
-
|
|
21
|
-
|
|
40
|
+
.modal_searchbar__header {
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: center;
|
|
44
|
+
margin-bottom: 1rem;
|
|
22
45
|
}
|
|
23
46
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
47
|
+
.modal_searchbar__title {
|
|
48
|
+
font-size: 1.5rem;
|
|
49
|
+
font-weight: bold;
|
|
50
|
+
color: var(--others-black);
|
|
28
51
|
}
|
|
29
52
|
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
&:hover {
|
|
35
|
-
color: var(--others-black);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
&__emphasis {
|
|
39
|
-
font-style: normal;
|
|
40
|
-
font-weight: normal;
|
|
41
|
-
color: var(--others-black);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
&--all {
|
|
45
|
-
font-weight: bold;
|
|
46
|
-
animation: none;
|
|
53
|
+
.dropdown_input {
|
|
54
|
+
.search {
|
|
55
|
+
width: 100%;
|
|
56
|
+
margin: 0;
|
|
47
57
|
}
|
|
48
58
|
}
|
|
49
59
|
}
|
|
50
60
|
}
|
|
51
|
-
|
|
52
|
-
@keyframes newLine {
|
|
53
|
-
0% {
|
|
54
|
-
opacity: 0;
|
|
55
|
-
line-height: 0rem;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
100% {
|
|
59
|
-
opacity: 1;
|
|
60
|
-
line-height: 1.5rem;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
61
|
`
|
|
@@ -1,66 +1,106 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
1
|
+
import React, { useEffect, useRef } from 'react'
|
|
3
2
|
import { DropdownInput } from '../../atoms/DropdownInput/DropdownInput'
|
|
4
3
|
import { SearchIcon } from '../../../../images/componentsSvg/SearchIcon'
|
|
5
4
|
import { useWindowSize } from '../../../hooks/useWindowSize'
|
|
6
5
|
|
|
7
6
|
import { type SearchBarProps } from './SearchBarProps.types'
|
|
8
7
|
import { SearchBarStyled } from './SearchBar.styled'
|
|
8
|
+
import { useSearchFunction } from '../../../hooks/useSearchFunction'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const
|
|
10
|
+
const DesktopSearchBar: React.FC<SearchBarProps> = ({ products, searchBarTexts, routes, handleResultClick }) => {
|
|
11
|
+
const { results, searchFunction } = useSearchFunction({
|
|
12
|
+
products,
|
|
13
|
+
searchBarTexts,
|
|
14
|
+
routes,
|
|
15
|
+
handleResultClick
|
|
16
|
+
})
|
|
17
|
+
const searchInputRef = useRef<HTMLInputElement>(null)
|
|
18
|
+
const searchBarContainerRef = useRef<HTMLDivElement>(null)
|
|
19
|
+
const isResultsVisible = Array.isArray(results) && results.length > 0
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
23
|
+
if (event.key === 'Escape') {
|
|
24
|
+
searchFunction('')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
28
|
+
if (searchBarContainerRef.current && !searchBarContainerRef.current.contains(event.target as Node)) {
|
|
29
|
+
searchFunction('')
|
|
30
|
+
}
|
|
31
|
+
}
|
|
17
32
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
|
|
22
|
-
const preMatch = product.slice(0, product.toLowerCase().indexOf(searchTerm))
|
|
23
|
-
const match = product.slice(product.toLowerCase().indexOf(searchTerm), preMatch.length + searchTerm.length)
|
|
24
|
-
const postMatch = product.slice(product.toLowerCase().indexOf(searchTerm) + searchTerm.length, product.length)
|
|
25
|
-
const link = item.categoryUrl ? `${item.categoryUrl}/${item.slug}` : item.slug
|
|
26
|
-
return (
|
|
27
|
-
<li key={searchBarTexts.title} className='dropdown_input__item'>
|
|
28
|
-
<a
|
|
29
|
-
href={routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link)}
|
|
30
|
-
className='dropdown_input__link'
|
|
31
|
-
key={item.linkText}
|
|
32
|
-
onClick={(e) => {
|
|
33
|
-
e.preventDefault()
|
|
34
|
-
handleResultClick(product, routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link))
|
|
35
|
-
}}
|
|
36
|
-
title={product}
|
|
37
|
-
>
|
|
38
|
-
{preMatch}
|
|
39
|
-
<strong className='dropdown_input__link__emphasis'>{match}</strong>
|
|
40
|
-
{postMatch}
|
|
41
|
-
</a>
|
|
42
|
-
</li>
|
|
43
|
-
)
|
|
44
|
-
})
|
|
45
|
-
.slice(0, 9)
|
|
33
|
+
if (isResultsVisible) {
|
|
34
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
35
|
+
document.addEventListener('mousedown', handleClickOutside)
|
|
36
|
+
}
|
|
46
37
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
</li>
|
|
53
|
-
)
|
|
38
|
+
return () => {
|
|
39
|
+
document.removeEventListener('keydown', handleKeyDown)
|
|
40
|
+
document.removeEventListener('mousedown', handleClickOutside)
|
|
41
|
+
}
|
|
42
|
+
}, [isResultsVisible, searchFunction])
|
|
54
43
|
|
|
55
|
-
|
|
56
|
-
|
|
44
|
+
return (
|
|
45
|
+
<SearchBarStyled ref={searchBarContainerRef} className='modal_searchbar'>
|
|
46
|
+
<div className='modal_searchbar__content'>
|
|
47
|
+
<DropdownInput
|
|
48
|
+
ref={searchInputRef}
|
|
49
|
+
name='search'
|
|
50
|
+
className='search'
|
|
51
|
+
placeholder={searchBarTexts.placeholder}
|
|
52
|
+
icon={<SearchIcon />}
|
|
53
|
+
onChange={(text: string) => {
|
|
54
|
+
searchFunction(text)
|
|
55
|
+
}}
|
|
56
|
+
results={results}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
</SearchBarStyled>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const MobileSearchBar: React.FC<SearchBarProps> = ({ products, searchBarTexts, routes, handleResultClick }) => {
|
|
64
|
+
const { results, searchFunction } = useSearchFunction({
|
|
65
|
+
products,
|
|
66
|
+
searchBarTexts,
|
|
67
|
+
routes,
|
|
68
|
+
handleResultClick
|
|
69
|
+
})
|
|
70
|
+
const searchInputRef = useRef<HTMLInputElement>(null)
|
|
71
|
+
const searchBarContainerRef = useRef<HTMLDivElement>(null)
|
|
72
|
+
const isResultsVisible = Array.isArray(results) && results.length > 0
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
76
|
+
if (event.key === 'Escape') {
|
|
77
|
+
searchFunction('')
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
81
|
+
if (searchBarContainerRef.current && !searchBarContainerRef.current.contains(event.target as Node)) {
|
|
82
|
+
searchFunction('')
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isResultsVisible) {
|
|
87
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
88
|
+
document.addEventListener('mousedown', handleClickOutside)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return () => {
|
|
92
|
+
document.removeEventListener('keydown', handleKeyDown)
|
|
93
|
+
document.removeEventListener('mousedown', handleClickOutside)
|
|
94
|
+
}
|
|
95
|
+
}, [isResultsVisible, searchFunction])
|
|
57
96
|
|
|
58
97
|
return (
|
|
59
|
-
<SearchBarStyled>
|
|
98
|
+
<SearchBarStyled ref={searchBarContainerRef}>
|
|
60
99
|
<DropdownInput
|
|
100
|
+
ref={searchInputRef}
|
|
61
101
|
name='search'
|
|
62
102
|
className='search'
|
|
63
|
-
placeholder={
|
|
103
|
+
placeholder={searchBarTexts.placeholder}
|
|
64
104
|
icon={<SearchIcon />}
|
|
65
105
|
onChange={(text: string) => {
|
|
66
106
|
searchFunction(text)
|
|
@@ -70,3 +110,14 @@ export const SearchBar: React.FC<SearchBarProps> = ({ products, searchBarTexts,
|
|
|
70
110
|
</SearchBarStyled>
|
|
71
111
|
)
|
|
72
112
|
}
|
|
113
|
+
|
|
114
|
+
export const SearchBar: React.FC<SearchBarProps> = (props) => {
|
|
115
|
+
const windowSize = useWindowSize()
|
|
116
|
+
const isDesktop = !!windowSize.width && windowSize.width >= 960
|
|
117
|
+
|
|
118
|
+
if (isDesktop) {
|
|
119
|
+
return <DesktopSearchBar {...props} />
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return <MobileSearchBar {...props} />
|
|
123
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type SearchBarProps } from '../components/molecules/SearchBar/SearchBarProps.types';
|
|
3
|
+
interface SearchFunctionProps extends SearchBarProps {
|
|
4
|
+
onClose?: () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare const useSearchFunction: (props: SearchFunctionProps) => {
|
|
7
|
+
results: React.JSX.Element[];
|
|
8
|
+
searchFunction: (text: string) => void;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
export const useSearchFunction = (props) => {
|
|
4
|
+
const [results, setResults] = useState([]);
|
|
5
|
+
const searchFunction = (text) => {
|
|
6
|
+
const { products, searchBarTexts, routes, handleResultClick, onClose } = props;
|
|
7
|
+
const searchTerm = text.toLowerCase();
|
|
8
|
+
const productsFiltered = products.filter((item) => item.linkText.toLowerCase().includes(searchTerm));
|
|
9
|
+
const newResults = productsFiltered
|
|
10
|
+
.map((item) => {
|
|
11
|
+
const product = item.linkText;
|
|
12
|
+
const preMatch = product.slice(0, product.toLowerCase().indexOf(searchTerm));
|
|
13
|
+
const match = product.slice(product.toLowerCase().indexOf(searchTerm), preMatch.length + searchTerm.length);
|
|
14
|
+
const postMatch = product.slice(product.toLowerCase().indexOf(searchTerm) + searchTerm.length, product.length);
|
|
15
|
+
const link = item.categoryUrl ? `${item.categoryUrl}/${item.slug}` : item.slug;
|
|
16
|
+
return (_jsx("li", { className: 'dropdown_input__item', children: _jsxs("a", { href: routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link), className: 'dropdown_input__link', onClick: (e) => {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
handleResultClick(product, routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link));
|
|
19
|
+
if (onClose)
|
|
20
|
+
onClose();
|
|
21
|
+
}, title: product, children: [preMatch, _jsx("strong", { className: 'dropdown_input__link__emphasis', children: match }), postMatch] }) }, item.linkText));
|
|
22
|
+
})
|
|
23
|
+
.slice(0, 9);
|
|
24
|
+
newResults.push(_jsx("li", { className: 'dropdown_input__item', children: _jsx("a", { className: 'dropdown_input__link--all', title: searchBarTexts.title, href: routes.LEGAL_DOCUMENTS, onClick: onClose, children: searchBarTexts.title }) }, searchBarTexts.title));
|
|
25
|
+
setResults(newResults);
|
|
26
|
+
};
|
|
27
|
+
return { results, searchFunction };
|
|
28
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { type SearchBarProps } from '../components/molecules/SearchBar/SearchBarProps.types'
|
|
3
|
+
|
|
4
|
+
interface SearchFunctionProps extends SearchBarProps {
|
|
5
|
+
onClose?: () => void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const useSearchFunction = (props: SearchFunctionProps) => {
|
|
9
|
+
const [results, setResults] = useState<React.JSX.Element[]>([])
|
|
10
|
+
|
|
11
|
+
const searchFunction = (text: string): void => {
|
|
12
|
+
const { products, searchBarTexts, routes, handleResultClick, onClose } = props
|
|
13
|
+
const searchTerm = text.toLowerCase()
|
|
14
|
+
|
|
15
|
+
const productsFiltered = products.filter((item) => item.linkText.toLowerCase().includes(searchTerm))
|
|
16
|
+
|
|
17
|
+
const newResults = productsFiltered
|
|
18
|
+
.map((item) => {
|
|
19
|
+
const product = item.linkText
|
|
20
|
+
const preMatch = product.slice(0, product.toLowerCase().indexOf(searchTerm))
|
|
21
|
+
const match = product.slice(product.toLowerCase().indexOf(searchTerm), preMatch.length + searchTerm.length)
|
|
22
|
+
const postMatch = product.slice(product.toLowerCase().indexOf(searchTerm) + searchTerm.length, product.length)
|
|
23
|
+
const link = item.categoryUrl ? `${item.categoryUrl}/${item.slug}` : item.slug
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<li key={item.linkText} className='dropdown_input__item'>
|
|
27
|
+
<a
|
|
28
|
+
href={routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link)}
|
|
29
|
+
className='dropdown_input__link'
|
|
30
|
+
onClick={(e) => {
|
|
31
|
+
e.preventDefault()
|
|
32
|
+
handleResultClick(product, routes.CUSTOM_URL_FROM_TARGET_ADDRESS(link))
|
|
33
|
+
if (onClose) onClose()
|
|
34
|
+
}}
|
|
35
|
+
title={product}
|
|
36
|
+
>
|
|
37
|
+
{preMatch}
|
|
38
|
+
<strong className='dropdown_input__link__emphasis'>{match}</strong>
|
|
39
|
+
{postMatch}
|
|
40
|
+
</a>
|
|
41
|
+
</li>
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
.slice(0, 9)
|
|
45
|
+
|
|
46
|
+
newResults.push(
|
|
47
|
+
<li key={searchBarTexts.title} className='dropdown_input__item'>
|
|
48
|
+
<a
|
|
49
|
+
className='dropdown_input__link--all'
|
|
50
|
+
title={searchBarTexts.title}
|
|
51
|
+
href={routes.LEGAL_DOCUMENTS}
|
|
52
|
+
onClick={onClose}
|
|
53
|
+
>
|
|
54
|
+
{searchBarTexts.title}
|
|
55
|
+
</a>
|
|
56
|
+
</li>
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
setResults(newResults)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { results, searchFunction }
|
|
63
|
+
}
|