@netlify/spark-ui 0.0.12 → 0.0.14
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/assets/KeyboardKey.css +1 -0
- package/dist/assets/SearchHeading.css +1 -0
- package/dist/assets/SearchModal.css +1 -0
- package/dist/assets/SearchToggle.css +1 -1
- package/dist/{compat.module-DWiGVdMB.js → chunks/compat.module.BPxt-oTe.js} +2 -2
- package/dist/components/index.d.ts +4 -4
- package/dist/components/preact/Icon/index.js +1 -1
- package/dist/components/preact/KeyboardKey/KeyboardKey.d.ts +5 -0
- package/dist/components/preact/KeyboardKey/KeyboardKey.js +7 -0
- package/dist/components/preact/Modal/{index.js → Modal.js} +2 -2
- package/dist/components/preact/SearchModal/components/{SearchHeading.d.ts → SearchHeading/SearchHeading.d.ts} +2 -2
- package/dist/components/preact/SearchModal/components/SearchHeading/SearchHeading.js +5 -0
- package/dist/components/preact/SearchModal/components/SearchInput.d.ts +2 -3
- package/dist/components/preact/SearchModal/components/SearchInput.js +11 -11
- package/dist/components/preact/SearchModal/components/SearchLink.d.ts +1 -2
- package/dist/components/preact/SearchModal/components/SearchLink.js +10 -10
- package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.d.ts +7 -0
- package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.js +98 -0
- package/dist/components/preact/SearchModal/components/SearchToggle/SearchToggle.js +3 -3
- package/dist/components/preact/SearchModal/components/SearchWindow.d.ts +1 -2
- package/dist/components/preact/SearchModal/components/SearchWindow.js +10 -10
- package/dist/components/preact/SearchModal/hooks/index.d.ts +5 -0
- package/dist/components/preact/SearchModal/hooks/index.js +12 -0
- package/dist/components/preact/SearchModal/hooks/useKeyboardNav.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearch.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchHotkeys.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchParams.js +1 -1
- package/dist/components/preact/SearchModal/hooks/useSearchToggles.js +1 -1
- package/dist/components/preact/SearchModal/index.d.ts +6 -6
- package/dist/components/preact/SearchModal/index.js +12 -55
- package/dist/components/preact/index.d.ts +4 -4
- package/dist/components/preact/index.js +16 -14
- package/package.json +6 -6
- package/packages/components/index.ts +4 -4
- package/packages/components/preact/KeyboardKey/KeyboardKey.css +10 -12
- package/packages/components/preact/KeyboardKey/{index.tsx → KeyboardKey.tsx} +1 -3
- package/packages/components/preact/Modal/{index.tsx → Modal.tsx} +1 -1
- package/packages/components/preact/SearchModal/components/SearchHeading/SearchHeading.css +7 -0
- package/packages/components/preact/SearchModal/components/{SearchHeading.tsx → SearchHeading/SearchHeading.tsx} +4 -2
- package/packages/components/preact/SearchModal/components/SearchInput.tsx +5 -6
- package/packages/components/preact/SearchModal/components/SearchLink.tsx +5 -6
- package/packages/{styles/search.css → components/preact/SearchModal/components/SearchModal/SearchModal.css} +59 -87
- package/packages/components/preact/SearchModal/components/SearchModal/SearchModal.tsx +78 -0
- package/packages/components/preact/SearchModal/components/SearchToggle/SearchToggle.css +2 -2
- package/packages/components/preact/SearchModal/components/SearchToggle/SearchToggle.tsx +1 -1
- package/packages/components/preact/SearchModal/components/SearchWindow.tsx +6 -8
- package/packages/components/preact/SearchModal/hooks/index.ts +5 -0
- package/packages/components/preact/SearchModal/index.tsx +6 -72
- package/packages/components/preact/SearchModal/types/search.types.tsx +1 -1
- package/packages/components/preact/index.ts +4 -4
- package/dist/assets/index.css +0 -1
- package/dist/assets/index2.css +0 -1
- package/dist/components/preact/KeyboardKey/index.d.ts +0 -6
- package/dist/components/preact/KeyboardKey/index.js +0 -7
- package/dist/components/preact/SearchModal/components/SearchFooter.d.ts +0 -6
- package/dist/components/preact/SearchModal/components/SearchFooter.js +0 -7
- package/dist/components/preact/SearchModal/components/SearchFooterTip.d.ts +0 -6
- package/dist/components/preact/SearchModal/components/SearchFooterTip.js +0 -7
- package/dist/components/preact/SearchModal/components/SearchHeading.js +0 -5
- package/dist/components/preact/SearchModal/components/index.d.ts +0 -7
- package/dist/components/preact/SearchModal/components/index.js +0 -16
- package/packages/components/preact/SearchModal/components/SearchFooter.tsx +0 -11
- package/packages/components/preact/SearchModal/components/SearchFooterTip.tsx +0 -11
- package/packages/components/preact/SearchModal/components/index.ts +0 -7
- /package/dist/{hooks.module-ExpuRnbo.js → chunks/hooks.module.ExpuRnbo.js} +0 -0
- /package/dist/{jsxRuntime.module-Bzuv3cXw.js → chunks/jsxRuntime.module.Bzuv3cXw.js} +0 -0
- /package/dist/components/preact/Modal/{index.d.ts → Modal.d.ts} +0 -0
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
--
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
}
|
|
1
|
+
.n-keyboard-key {
|
|
2
|
+
--n-key-text-size: .8em;
|
|
3
|
+
--n-key-border-radius: 6px;
|
|
4
|
+
--n-key-text-color: currentColor;
|
|
5
|
+
--n-key-bg-color: transparent;
|
|
7
6
|
|
|
8
|
-
.keyboard-key {
|
|
9
7
|
display: flex;
|
|
10
8
|
gap: calc(var(--space-3xs) * .5);
|
|
11
|
-
font-size: var(--
|
|
12
|
-
color: var(--
|
|
13
|
-
background: var(--
|
|
9
|
+
font-size: var(--n-key-text-size);
|
|
10
|
+
color: var(--n-key-text-color);
|
|
11
|
+
background: var(--n-key-bg-color);
|
|
14
12
|
border: 1px solid currentColor;
|
|
15
|
-
border-radius: var(--
|
|
16
|
-
padding: var(--
|
|
13
|
+
border-radius: var(--n-key-border-radius);
|
|
14
|
+
padding: var(--n-key-padding-block, .05em) var(--n-key-padding-inline, .3em);
|
|
17
15
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { h } from 'preact';
|
|
2
|
-
|
|
3
1
|
import './KeyboardKey.css';
|
|
4
2
|
|
|
5
3
|
interface Props {
|
|
@@ -8,7 +6,7 @@ interface Props {
|
|
|
8
6
|
|
|
9
7
|
function KeyboardKey(props: Props) {
|
|
10
8
|
return (
|
|
11
|
-
<span class="keyboard-key">
|
|
9
|
+
<span class="n-keyboard-key">
|
|
12
10
|
{props.keyNames.map((keyName, idx) => (
|
|
13
11
|
<span key={idx}>{keyName}</span>
|
|
14
12
|
))}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ComponentChildren } from 'preact';
|
|
2
|
+
|
|
3
|
+
import './SearchHeading.css';
|
|
2
4
|
|
|
3
5
|
type SearchHeadingProps = {
|
|
4
6
|
children: ComponentChildren;
|
|
5
7
|
};
|
|
6
8
|
|
|
7
9
|
const SearchHeading = ({ children }: SearchHeadingProps) => {
|
|
8
|
-
return <h2 class="search-
|
|
10
|
+
return <h2 class="n-search-heading">{children}</h2>;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
export default SearchHeading;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { h } from 'preact';
|
|
2
1
|
import { useState, useEffect } from 'preact/hooks';
|
|
3
2
|
import Icon from '../../Icon';
|
|
4
3
|
|
|
5
|
-
interface Props
|
|
4
|
+
interface Props {
|
|
6
5
|
setSearchTerm: (term: string) => void;
|
|
7
6
|
placeholder?: string;
|
|
8
7
|
initialValue?: string;
|
|
@@ -24,15 +23,15 @@ const SearchInput = (props: Props) => {
|
|
|
24
23
|
}, [props.initialValue, setValue]);
|
|
25
24
|
|
|
26
25
|
return (
|
|
27
|
-
<div class="search-input-wrapper">
|
|
28
|
-
<label class="search-label" htmlFor="search">
|
|
26
|
+
<div class="n-search-input-wrapper">
|
|
27
|
+
<label class="n-search-label" htmlFor="search">
|
|
29
28
|
<span class="visually-hidden">Search</span>
|
|
30
|
-
<div class="search-icon">
|
|
29
|
+
<div class="n-search-icon">
|
|
31
30
|
<Icon name="search" />
|
|
32
31
|
</div>
|
|
33
32
|
</label>
|
|
34
33
|
<input
|
|
35
|
-
class="search-input"
|
|
34
|
+
class="n-search-input"
|
|
36
35
|
type="text"
|
|
37
36
|
value={value}
|
|
38
37
|
placeholder={props.placeholder || 'Search...'}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { h } from 'preact';
|
|
2
1
|
import Icon, { type IconName } from '../../Icon';
|
|
3
2
|
|
|
4
3
|
export interface Props {
|
|
@@ -9,11 +8,11 @@ export interface Props {
|
|
|
9
8
|
excerpt?: string;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
const SearchLink = ({ icon, title,
|
|
11
|
+
const SearchLink = ({ icon, title, url, excerpt }: Props) => {
|
|
13
12
|
return (
|
|
14
|
-
<a className="result-link" href={url}>
|
|
15
|
-
<div className="result-header">
|
|
16
|
-
<div className="result-title">
|
|
13
|
+
<a className="n-result-link" href={url}>
|
|
14
|
+
<div className="n-result-header">
|
|
15
|
+
<div className="n-result-title">
|
|
17
16
|
{icon && (
|
|
18
17
|
<span className="icon">
|
|
19
18
|
<Icon name={icon} />
|
|
@@ -25,7 +24,7 @@ const SearchLink = ({ icon, title, content_type, url, excerpt }: Props) => {
|
|
|
25
24
|
<Icon name="caretRight" />
|
|
26
25
|
</div>
|
|
27
26
|
</div>
|
|
28
|
-
{excerpt && <p className="result-excerpt" dangerouslySetInnerHTML={{ __html: excerpt }} />}
|
|
27
|
+
{excerpt && <p className="n-result-excerpt" dangerouslySetInnerHTML={{ __html: excerpt }} />}
|
|
29
28
|
</a>
|
|
30
29
|
);
|
|
31
30
|
};
|
|
@@ -1,106 +1,86 @@
|
|
|
1
|
-
/* Imports */
|
|
2
|
-
@import url('./tokens.css');
|
|
3
|
-
@import url('./utils.css');
|
|
4
|
-
|
|
5
1
|
/* Root Variables */
|
|
6
|
-
.search-modal {
|
|
7
|
-
--
|
|
8
|
-
--
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
13
|
-
--
|
|
14
|
-
--
|
|
2
|
+
.n-search-modal {
|
|
3
|
+
--n-search-padding-inline: .5em;
|
|
4
|
+
--n-search-color-text: var(--color-text-1, currentColor);
|
|
5
|
+
--n-search-color-text-secondary: var(--color-text-2, currentColor);
|
|
6
|
+
--n-search-color-bg: var(--color-bg-1);
|
|
7
|
+
--n-search-color-bg-2: var(--color-bg-2);
|
|
8
|
+
--n-search-color-border: var(--color-bg-3);
|
|
9
|
+
--n-search-border-radius: 8px;
|
|
10
|
+
--n-search-max-w: 600px;
|
|
11
|
+
--n-search-text-highlight: var(--color-text-accent);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.n-search-modal {
|
|
15
|
+
padding: 0;
|
|
16
|
+
border: none;
|
|
17
|
+
border-radius: var(--n-search-border-radius);
|
|
18
|
+
width: min(var(--n-search-max-w), 100%);
|
|
19
|
+
margin-inline: auto;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
/* Container Styles */
|
|
18
|
-
.search-container {
|
|
19
|
-
--mark-bg: var(--
|
|
23
|
+
.n-search-container {
|
|
24
|
+
--mark-bg: var(--n-search-text-highlight);
|
|
20
25
|
display: grid;
|
|
21
|
-
width: min(var(--
|
|
26
|
+
width: min(var(--n-search-max-w), 100%);
|
|
22
27
|
min-height: 470px;
|
|
23
|
-
background-color: var(--
|
|
24
|
-
border-radius: var(--
|
|
28
|
+
background-color: var(--n-search-color-bg);
|
|
29
|
+
border-radius: var(--n-search-border-radius);
|
|
25
30
|
overflow: hidden;
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
.search-modal {
|
|
29
|
-
padding: 0;
|
|
30
|
-
border: none;
|
|
31
|
-
border-radius: var(--ntl-search-border-radius);
|
|
32
|
-
width: min(var(--ntl-search-max-w), 100%);
|
|
33
|
-
margin-inline: auto;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
33
|
/* Search Bar */
|
|
37
|
-
.search {
|
|
34
|
+
.n-search-bar {
|
|
38
35
|
display: flex;
|
|
39
36
|
flex-wrap: wrap;
|
|
40
37
|
align-items: center;
|
|
41
38
|
overflow: hidden;
|
|
42
|
-
background: var(--
|
|
43
|
-
border-bottom: 1px solid var(--
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.search > * {
|
|
47
|
-
display: inline-block;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.search-trigger {
|
|
51
|
-
width: var(--ntl-search-icon-size, 1rem);
|
|
52
|
-
height: auto;
|
|
53
|
-
border: none;
|
|
54
|
-
background: none;
|
|
55
|
-
padding: 0;
|
|
56
|
-
cursor: pointer;
|
|
57
|
-
padding-inline: var(--space-2xs);
|
|
58
|
-
color: var(--color-text-1);
|
|
59
|
-
box-sizing: content-box;
|
|
60
|
-
display: block;
|
|
39
|
+
background: var(--n-search-color-bg);
|
|
40
|
+
border-bottom: 1px solid var(--n-search-color-border);
|
|
61
41
|
}
|
|
62
42
|
|
|
63
43
|
/* Search Input */
|
|
64
|
-
.search-input-wrapper {
|
|
44
|
+
.n-search-input-wrapper {
|
|
65
45
|
all: unset;
|
|
66
46
|
display: flex;
|
|
67
47
|
width: 100%;
|
|
68
48
|
}
|
|
69
49
|
|
|
70
|
-
.search-input {
|
|
50
|
+
.n-search-input {
|
|
71
51
|
display: inline-flex;
|
|
72
52
|
box-sizing: border-box;
|
|
73
|
-
background: var(--
|
|
53
|
+
background: var(--n-search-color-bg);
|
|
74
54
|
inline-size: 100%;
|
|
75
55
|
padding-block: .75rem;
|
|
76
|
-
padding-inline: var(--
|
|
56
|
+
padding-inline: var(--n-search-padding-inline);
|
|
77
57
|
flex: 1;
|
|
78
58
|
border: none;
|
|
79
59
|
outline: none;
|
|
80
60
|
font-size: 1rem;
|
|
81
61
|
}
|
|
82
62
|
|
|
83
|
-
.search-input::placeholder {
|
|
84
|
-
color: var(--
|
|
63
|
+
.n-search-input::placeholder {
|
|
64
|
+
color: var(--n-search-color-text);
|
|
85
65
|
}
|
|
86
66
|
|
|
87
67
|
/* Search Label */
|
|
88
|
-
.search-label {
|
|
68
|
+
.n-search-label {
|
|
89
69
|
display: flex;
|
|
90
|
-
padding-inline: var(--
|
|
70
|
+
padding-inline: var(--n-search-padding-inline);
|
|
91
71
|
}
|
|
92
72
|
|
|
93
|
-
.search-label > * {
|
|
73
|
+
.n-search-label > * {
|
|
94
74
|
display: inline-block;
|
|
95
75
|
margin: 0;
|
|
96
76
|
}
|
|
97
77
|
|
|
98
78
|
/* Icons */
|
|
99
|
-
.search-icon {
|
|
79
|
+
.n-search-icon {
|
|
100
80
|
display: flex;
|
|
101
81
|
width: 1em;
|
|
102
82
|
height: auto;
|
|
103
|
-
color:
|
|
83
|
+
color: var(--n-search-color-text-secondary);
|
|
104
84
|
}
|
|
105
85
|
|
|
106
86
|
.icon {
|
|
@@ -112,70 +92,62 @@
|
|
|
112
92
|
|
|
113
93
|
.icon [data-icon="caretRight"] {
|
|
114
94
|
width: 10px;
|
|
115
|
-
color: var(--
|
|
95
|
+
color: var(--n-search-color-text-secondary);
|
|
116
96
|
}
|
|
117
97
|
|
|
118
98
|
/* Search Key & Term */
|
|
119
|
-
.search-term {
|
|
99
|
+
.n-search-term {
|
|
120
100
|
font-weight: var(--font-medium);
|
|
121
101
|
font-size: 1.1em;
|
|
122
102
|
}
|
|
123
103
|
|
|
124
104
|
/* Search Results */
|
|
125
|
-
.search-
|
|
126
|
-
padding-inline: 1rem;
|
|
127
|
-
margin-block: var(--space-xs);
|
|
128
|
-
font-size: var(--step--2);
|
|
129
|
-
font-weight: var(--font-regular);
|
|
130
|
-
color: var(--color-text-3);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.search-window {
|
|
105
|
+
.n-search-window {
|
|
134
106
|
height: 400px;
|
|
135
107
|
overflow-x: hidden;
|
|
136
108
|
overflow-y: auto;
|
|
137
109
|
overscroll-behavior: contain;
|
|
138
110
|
margin-block: 0;
|
|
139
|
-
background: var(--
|
|
111
|
+
background: var(--n-search-color-bg);
|
|
140
112
|
}
|
|
141
113
|
|
|
142
|
-
.results-list, ul[role="list"] {
|
|
114
|
+
.n-results-list, ul[role="list"] {
|
|
143
115
|
list-style: none;
|
|
144
116
|
padding: 0;
|
|
145
117
|
}
|
|
146
118
|
|
|
147
|
-
.results-list-item {
|
|
119
|
+
.n-results-list-item {
|
|
148
120
|
border-bottom: 1px solid var(--color-bg-3);
|
|
149
121
|
}
|
|
150
|
-
.results-list-item:first-of-type {
|
|
122
|
+
.n-results-list-item:first-of-type {
|
|
151
123
|
border-top: 1px solid var(--color-bg-3);
|
|
152
124
|
}
|
|
153
125
|
|
|
154
126
|
/* Result Items */
|
|
155
|
-
.result-link {
|
|
127
|
+
.n-result-link {
|
|
156
128
|
all: unset;
|
|
157
129
|
display: flex;
|
|
158
130
|
flex-wrap: wrap;
|
|
159
131
|
row-gap: var(--space-3xs);
|
|
160
|
-
padding: var(--
|
|
132
|
+
padding: var(--n-result-padding-block, 1em) var(--n-result-padding-inline, 1rem);
|
|
161
133
|
font-size: var(--step--1);
|
|
162
134
|
font-weight: var(--font-regular);
|
|
163
135
|
text-decoration: none;
|
|
164
136
|
cursor: pointer;
|
|
165
137
|
}
|
|
166
138
|
|
|
167
|
-
.result-link:is(:hover, :focus-within) {
|
|
168
|
-
background: var(--
|
|
139
|
+
.n-result-link:is(:hover, :focus-within) {
|
|
140
|
+
background: var(--n-search-color-bg-2);
|
|
169
141
|
}
|
|
170
142
|
|
|
171
|
-
.result-header {
|
|
143
|
+
.n-result-header {
|
|
172
144
|
display: flex;
|
|
173
145
|
justify-content: space-between;
|
|
174
146
|
width: 100%;
|
|
175
147
|
align-items: center;
|
|
176
148
|
}
|
|
177
149
|
|
|
178
|
-
.result-title {
|
|
150
|
+
.n-result-title {
|
|
179
151
|
display: flex;
|
|
180
152
|
align-items: center;
|
|
181
153
|
gap: var(--space-s);
|
|
@@ -183,7 +155,7 @@
|
|
|
183
155
|
color: var(--color-text-2);
|
|
184
156
|
}
|
|
185
157
|
|
|
186
|
-
.result-excerpt {
|
|
158
|
+
.n-result-excerpt {
|
|
187
159
|
color: var(--color-text-3);
|
|
188
160
|
line-height: 1.3;
|
|
189
161
|
font-size: .9em;
|
|
@@ -191,17 +163,17 @@
|
|
|
191
163
|
}
|
|
192
164
|
|
|
193
165
|
/* Footer */
|
|
194
|
-
.search-footer {
|
|
195
|
-
border-top: 1px solid var(--
|
|
166
|
+
.n-search-footer {
|
|
167
|
+
border-top: 1px solid var(--n-search-color-border);
|
|
196
168
|
padding: var(--space-2xs) var(--space-s);
|
|
197
169
|
background: var(--color-bg-2);
|
|
198
170
|
display: flex;
|
|
199
171
|
gap: var(--space-m);
|
|
200
172
|
}
|
|
201
173
|
|
|
202
|
-
.search-footer-tip {
|
|
203
|
-
--
|
|
204
|
-
color: var(--
|
|
174
|
+
.n-search-footer-tip {
|
|
175
|
+
--n-key-text-color: var(--n-search-color-text-secondary);
|
|
176
|
+
color: var(--n-search-color-text-secondary);
|
|
205
177
|
display: flex;
|
|
206
178
|
gap: var(--space-2xs);
|
|
207
179
|
align-items: center;
|
|
@@ -209,7 +181,7 @@
|
|
|
209
181
|
}
|
|
210
182
|
|
|
211
183
|
/* Animations */
|
|
212
|
-
.search-modal {
|
|
184
|
+
.n-search-modal {
|
|
213
185
|
transition: display .2s allow-discrete, overlay .2s allow-discrete;
|
|
214
186
|
animation: closeSearch .2s forwards;
|
|
215
187
|
&[open] {
|
|
@@ -242,11 +214,11 @@
|
|
|
242
214
|
}
|
|
243
215
|
}
|
|
244
216
|
|
|
245
|
-
.search-modal::backdrop {
|
|
217
|
+
.n-search-modal::backdrop {
|
|
246
218
|
animation: closeSearchBackdrop .2s forwards;
|
|
247
219
|
}
|
|
248
220
|
|
|
249
|
-
.search-modal[open]::backdrop {
|
|
221
|
+
.n-search-modal[open]::backdrop {
|
|
250
222
|
animation: openSearchBackdrop .2s forwards;
|
|
251
223
|
}
|
|
252
224
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { type ComponentChildren } from 'preact';
|
|
2
|
+
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
3
|
+
import cn from "classnames"
|
|
4
|
+
|
|
5
|
+
import Modal from '@components/preact/Modal/Modal';
|
|
6
|
+
import KeyboardKey from '@components/preact/KeyboardKey/KeyboardKey';
|
|
7
|
+
import SearchWindow from '../../components/SearchWindow';
|
|
8
|
+
import SearchInput from '../../components/SearchInput';
|
|
9
|
+
import { useClickOutside } from '@utils/useClickOutside';
|
|
10
|
+
import {
|
|
11
|
+
useSearch,
|
|
12
|
+
useKeyboardNav,
|
|
13
|
+
useSearchHotkeys,
|
|
14
|
+
useSearchParams,
|
|
15
|
+
useSearchToggles,
|
|
16
|
+
} from '../../hooks';
|
|
17
|
+
|
|
18
|
+
import './SearchModal.css';
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
children: ComponentChildren;
|
|
22
|
+
className: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function SearchModal(props: Props) {
|
|
26
|
+
const { children, className, ...rest } = props;
|
|
27
|
+
const { state, actions } = useSearch();
|
|
28
|
+
const [searchOpen, setSearchOpen] = useState(false);
|
|
29
|
+
|
|
30
|
+
const openSearch = () => setSearchOpen(true);
|
|
31
|
+
const closeSearch = () => setSearchOpen(false);
|
|
32
|
+
|
|
33
|
+
const modalRef = useRef<HTMLDialogElement>(null);
|
|
34
|
+
const containerRef = useClickOutside<HTMLDivElement>(closeSearch);
|
|
35
|
+
|
|
36
|
+
useSearchToggles(openSearch);
|
|
37
|
+
useSearchParams(actions.setSearchTerm, openSearch);
|
|
38
|
+
useSearchHotkeys(searchOpen, openSearch, closeSearch);
|
|
39
|
+
useKeyboardNav(modalRef, searchOpen, closeSearch);
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!modalRef.current) return;
|
|
43
|
+
searchOpen ? modalRef.current.showModal() : modalRef.current.close();
|
|
44
|
+
}, [searchOpen]);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Modal ref={modalRef} className={cn(className, 'n-search-modal')} {...rest}>
|
|
48
|
+
<div ref={containerRef} className="n-search-container">
|
|
49
|
+
<form className="n-search-bar">
|
|
50
|
+
<SearchInput setSearchTerm={actions.setSearchTerm} initialValue={state.searchTerm} />
|
|
51
|
+
</form>
|
|
52
|
+
|
|
53
|
+
<SearchWindow
|
|
54
|
+
searchLoading={state.isLoading}
|
|
55
|
+
searchTerm={state.searchTerm}
|
|
56
|
+
results={state.results}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</SearchWindow>
|
|
60
|
+
|
|
61
|
+
<div className="n-search-footer">
|
|
62
|
+
<p className="n-search-footer-tip">
|
|
63
|
+
<KeyboardKey keyNames={['Esc']} />
|
|
64
|
+
to close
|
|
65
|
+
</p>
|
|
66
|
+
<p className="n-search-footer-tip">
|
|
67
|
+
<KeyboardKey keyNames={['Tab']} />
|
|
68
|
+
<span>or</span>
|
|
69
|
+
<KeyboardKey keyNames={['↑', '↓']} />
|
|
70
|
+
to navigate
|
|
71
|
+
</p>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
</Modal>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default SearchModal;
|
|
@@ -10,7 +10,7 @@ interface Props {
|
|
|
10
10
|
|
|
11
11
|
export default forwardRef(function SearchToggle(props: Props, ref: Ref<HTMLButtonElement>) {
|
|
12
12
|
return (
|
|
13
|
-
<button id={props.id} ref={ref} class="search-toggle" disabled data-ntl-search-toggle>
|
|
13
|
+
<button id={props.id} ref={ref} class="n-search-toggle" disabled data-ntl-search-toggle>
|
|
14
14
|
<span class="visually-hidden">Search</span>
|
|
15
15
|
<Icon name={props.iconName || 'search'} />
|
|
16
16
|
</button>
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { h } from 'preact';
|
|
2
|
-
|
|
3
1
|
import type { FunctionComponent } from 'preact';
|
|
4
2
|
import type { ResultProps, SearchResultsProps, SearchWindowProps } from '../types/search.types';
|
|
5
|
-
import SearchHeading from './SearchHeading';
|
|
3
|
+
import SearchHeading from './SearchHeading/SearchHeading';
|
|
6
4
|
import SearchLink from './SearchLink';
|
|
7
5
|
|
|
8
6
|
/* --- Search Results Window (for active searches) --- */
|
|
@@ -14,7 +12,7 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({
|
|
|
14
12
|
if (searchLoading) {
|
|
15
13
|
return (
|
|
16
14
|
<SearchHeading>
|
|
17
|
-
Searching for <span className="search-term">{searchTerm}</span> ...
|
|
15
|
+
Searching for <span className="n-search-term">{searchTerm}</span> ...
|
|
18
16
|
</SearchHeading>
|
|
19
17
|
);
|
|
20
18
|
}
|
|
@@ -22,15 +20,15 @@ const SearchResults: FunctionComponent<SearchResultsProps> = ({
|
|
|
22
20
|
if (!results || results.length === 0) {
|
|
23
21
|
return (
|
|
24
22
|
<SearchHeading>
|
|
25
|
-
0 results for <span className="search-term">{searchTerm}</span>
|
|
23
|
+
0 results for <span className="n-search-term">{searchTerm}</span>
|
|
26
24
|
</SearchHeading>
|
|
27
25
|
);
|
|
28
26
|
}
|
|
29
27
|
|
|
30
28
|
return (
|
|
31
|
-
<ul className="results-list" role="list">
|
|
29
|
+
<ul className="n-results-list" role="list">
|
|
32
30
|
{results.slice(0, 15).map((result, idx) => (
|
|
33
|
-
<li key={idx} className="results-list-item">
|
|
31
|
+
<li key={idx} className="n-results-list-item">
|
|
34
32
|
<SearchLink {...result} />
|
|
35
33
|
</li>
|
|
36
34
|
))}
|
|
@@ -52,7 +50,7 @@ export default function SearchWindow({
|
|
|
52
50
|
};
|
|
53
51
|
|
|
54
52
|
return (
|
|
55
|
-
<div className="search-window">
|
|
53
|
+
<div className="n-search-window">
|
|
56
54
|
<div className="search-links">
|
|
57
55
|
<SearchLink {...askNetlify} />
|
|
58
56
|
{searchTerm ? (
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { useSearch } from '../hooks/useSearch';
|
|
2
|
+
export { useKeyboardNav } from '../hooks/useKeyboardNav';
|
|
3
|
+
export { useSearchHotkeys } from '../hooks/useSearchHotkeys';
|
|
4
|
+
export { useSearchParams } from '../hooks/useSearchParams';
|
|
5
|
+
export { useSearchToggles } from '../hooks/useSearchToggles';
|
|
@@ -1,72 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { useSearch } from './hooks/useSearch';
|
|
8
|
-
import { useKeyboardNav } from './hooks/useKeyboardNav';
|
|
9
|
-
import { useSearchHotkeys } from './hooks/useSearchHotkeys';
|
|
10
|
-
import { useSearchParams } from './hooks/useSearchParams';
|
|
11
|
-
import { useSearchToggles } from './hooks/useSearchToggles';
|
|
12
|
-
import { useClickOutside } from '../../../utils/useClickOutside';
|
|
13
|
-
|
|
14
|
-
import '../../../styles/search.css';
|
|
15
|
-
|
|
16
|
-
interface Props {
|
|
17
|
-
children: ComponentChildren;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function SearchModal({ children }: Props) {
|
|
21
|
-
const { state, actions } = useSearch();
|
|
22
|
-
const [searchOpen, setSearchOpen] = useState(false);
|
|
23
|
-
|
|
24
|
-
const openSearch = () => setSearchOpen(true);
|
|
25
|
-
const closeSearch = () => setSearchOpen(false);
|
|
26
|
-
|
|
27
|
-
const modalRef = useRef<HTMLDialogElement>(null);
|
|
28
|
-
const containerRef = useClickOutside<HTMLDivElement>(closeSearch);
|
|
29
|
-
|
|
30
|
-
useSearchToggles(openSearch);
|
|
31
|
-
useSearchParams(actions.setSearchTerm, openSearch);
|
|
32
|
-
useSearchHotkeys(searchOpen, openSearch, closeSearch);
|
|
33
|
-
useKeyboardNav(modalRef, searchOpen, closeSearch);
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (!modalRef.current) return;
|
|
37
|
-
searchOpen ? modalRef.current.showModal() : modalRef.current.close();
|
|
38
|
-
}, [searchOpen]);
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<Modal ref={modalRef} className="search-modal">
|
|
42
|
-
<div ref={containerRef} class="search-container">
|
|
43
|
-
<form class="search">
|
|
44
|
-
<SearchInput setSearchTerm={actions.setSearchTerm} initialValue={state.searchTerm} />
|
|
45
|
-
</form>
|
|
46
|
-
|
|
47
|
-
<SearchWindow
|
|
48
|
-
searchLoading={state.isLoading}
|
|
49
|
-
searchTerm={state.searchTerm}
|
|
50
|
-
results={state.results}
|
|
51
|
-
>
|
|
52
|
-
{children}
|
|
53
|
-
</SearchWindow>
|
|
54
|
-
|
|
55
|
-
<SearchFooter>
|
|
56
|
-
<SearchFooterTip>
|
|
57
|
-
<KeyboardKey keyNames={['Esc']} />
|
|
58
|
-
to close
|
|
59
|
-
</SearchFooterTip>
|
|
60
|
-
<SearchFooterTip>
|
|
61
|
-
<KeyboardKey keyNames={['Tab']} />
|
|
62
|
-
<span>or</span>
|
|
63
|
-
<KeyboardKey keyNames={['↑', '↓']} />
|
|
64
|
-
to navigate
|
|
65
|
-
</SearchFooterTip>
|
|
66
|
-
</SearchFooter>
|
|
67
|
-
</div>
|
|
68
|
-
</Modal>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export default SearchModal;
|
|
1
|
+
export { default as SearchHeading } from './components/SearchHeading/SearchHeading';
|
|
2
|
+
export { default as SearchInput } from './components/SearchInput';
|
|
3
|
+
export { default as SearchLink } from './components/SearchLink';
|
|
4
|
+
export { default as SearchToggle } from './components/SearchToggle/SearchToggle';
|
|
5
|
+
export { default as SearchWindow } from './components/SearchWindow';
|
|
6
|
+
export { default as SearchModal } from './components/SearchModal/SearchModal';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { default as KeyboardKey } from './KeyboardKey';
|
|
2
|
-
export { default as Modal } from './Modal';
|
|
1
|
+
export { default as KeyboardKey } from './KeyboardKey/KeyboardKey';
|
|
2
|
+
export { default as Modal } from './Modal/Modal';
|
|
3
3
|
export { default as Icon } from './Icon';
|
|
4
4
|
export { default as SearchLink } from './SearchModal/components/SearchLink';
|
|
5
|
-
export { default as SearchHeading } from './SearchModal/components/SearchHeading';
|
|
5
|
+
export { default as SearchHeading } from './SearchModal/components/SearchHeading/SearchHeading';
|
|
6
6
|
export { default as SearchToggle } from './SearchModal/components/SearchToggle/SearchToggle';
|
|
7
|
-
export {
|
|
7
|
+
export { SearchModal } from './SearchModal';
|
|
8
8
|
|
|
9
9
|
export { type IconName } from './Icon';
|