@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.
Files changed (67) hide show
  1. package/dist/assets/KeyboardKey.css +1 -0
  2. package/dist/assets/SearchHeading.css +1 -0
  3. package/dist/assets/SearchModal.css +1 -0
  4. package/dist/assets/SearchToggle.css +1 -1
  5. package/dist/{compat.module-DWiGVdMB.js → chunks/compat.module.BPxt-oTe.js} +2 -2
  6. package/dist/components/index.d.ts +4 -4
  7. package/dist/components/preact/Icon/index.js +1 -1
  8. package/dist/components/preact/KeyboardKey/KeyboardKey.d.ts +5 -0
  9. package/dist/components/preact/KeyboardKey/KeyboardKey.js +7 -0
  10. package/dist/components/preact/Modal/{index.js → Modal.js} +2 -2
  11. package/dist/components/preact/SearchModal/components/{SearchHeading.d.ts → SearchHeading/SearchHeading.d.ts} +2 -2
  12. package/dist/components/preact/SearchModal/components/SearchHeading/SearchHeading.js +5 -0
  13. package/dist/components/preact/SearchModal/components/SearchInput.d.ts +2 -3
  14. package/dist/components/preact/SearchModal/components/SearchInput.js +11 -11
  15. package/dist/components/preact/SearchModal/components/SearchLink.d.ts +1 -2
  16. package/dist/components/preact/SearchModal/components/SearchLink.js +10 -10
  17. package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.d.ts +7 -0
  18. package/dist/components/preact/SearchModal/components/SearchModal/SearchModal.js +98 -0
  19. package/dist/components/preact/SearchModal/components/SearchToggle/SearchToggle.js +3 -3
  20. package/dist/components/preact/SearchModal/components/SearchWindow.d.ts +1 -2
  21. package/dist/components/preact/SearchModal/components/SearchWindow.js +10 -10
  22. package/dist/components/preact/SearchModal/hooks/index.d.ts +5 -0
  23. package/dist/components/preact/SearchModal/hooks/index.js +12 -0
  24. package/dist/components/preact/SearchModal/hooks/useKeyboardNav.js +1 -1
  25. package/dist/components/preact/SearchModal/hooks/useSearch.js +1 -1
  26. package/dist/components/preact/SearchModal/hooks/useSearchHotkeys.js +1 -1
  27. package/dist/components/preact/SearchModal/hooks/useSearchParams.js +1 -1
  28. package/dist/components/preact/SearchModal/hooks/useSearchToggles.js +1 -1
  29. package/dist/components/preact/SearchModal/index.d.ts +6 -6
  30. package/dist/components/preact/SearchModal/index.js +12 -55
  31. package/dist/components/preact/index.d.ts +4 -4
  32. package/dist/components/preact/index.js +16 -14
  33. package/package.json +6 -6
  34. package/packages/components/index.ts +4 -4
  35. package/packages/components/preact/KeyboardKey/KeyboardKey.css +10 -12
  36. package/packages/components/preact/KeyboardKey/{index.tsx → KeyboardKey.tsx} +1 -3
  37. package/packages/components/preact/Modal/{index.tsx → Modal.tsx} +1 -1
  38. package/packages/components/preact/SearchModal/components/SearchHeading/SearchHeading.css +7 -0
  39. package/packages/components/preact/SearchModal/components/{SearchHeading.tsx → SearchHeading/SearchHeading.tsx} +4 -2
  40. package/packages/components/preact/SearchModal/components/SearchInput.tsx +5 -6
  41. package/packages/components/preact/SearchModal/components/SearchLink.tsx +5 -6
  42. package/packages/{styles/search.css → components/preact/SearchModal/components/SearchModal/SearchModal.css} +59 -87
  43. package/packages/components/preact/SearchModal/components/SearchModal/SearchModal.tsx +78 -0
  44. package/packages/components/preact/SearchModal/components/SearchToggle/SearchToggle.css +2 -2
  45. package/packages/components/preact/SearchModal/components/SearchToggle/SearchToggle.tsx +1 -1
  46. package/packages/components/preact/SearchModal/components/SearchWindow.tsx +6 -8
  47. package/packages/components/preact/SearchModal/hooks/index.ts +5 -0
  48. package/packages/components/preact/SearchModal/index.tsx +6 -72
  49. package/packages/components/preact/SearchModal/types/search.types.tsx +1 -1
  50. package/packages/components/preact/index.ts +4 -4
  51. package/dist/assets/index.css +0 -1
  52. package/dist/assets/index2.css +0 -1
  53. package/dist/components/preact/KeyboardKey/index.d.ts +0 -6
  54. package/dist/components/preact/KeyboardKey/index.js +0 -7
  55. package/dist/components/preact/SearchModal/components/SearchFooter.d.ts +0 -6
  56. package/dist/components/preact/SearchModal/components/SearchFooter.js +0 -7
  57. package/dist/components/preact/SearchModal/components/SearchFooterTip.d.ts +0 -6
  58. package/dist/components/preact/SearchModal/components/SearchFooterTip.js +0 -7
  59. package/dist/components/preact/SearchModal/components/SearchHeading.js +0 -5
  60. package/dist/components/preact/SearchModal/components/index.d.ts +0 -7
  61. package/dist/components/preact/SearchModal/components/index.js +0 -16
  62. package/packages/components/preact/SearchModal/components/SearchFooter.tsx +0 -11
  63. package/packages/components/preact/SearchModal/components/SearchFooterTip.tsx +0 -11
  64. package/packages/components/preact/SearchModal/components/index.ts +0 -7
  65. /package/dist/{hooks.module-ExpuRnbo.js → chunks/hooks.module.ExpuRnbo.js} +0 -0
  66. /package/dist/{jsxRuntime.module-Bzuv3cXw.js → chunks/jsxRuntime.module.Bzuv3cXw.js} +0 -0
  67. /package/dist/components/preact/Modal/{index.d.ts → Modal.d.ts} +0 -0
@@ -1,17 +1,15 @@
1
- :root {
2
- --ntl-key-text-size: .8em;
3
- --ntl-key-border-radius: 6px;
4
- --ntl-key-text-color: var(--neutral-300);
5
- --ntl-key-bg-color: transparent;
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(--ntl-key-text-size);
12
- color: var(--ntl-key-text-color);
13
- background: var(--ntl-key-bg-color);
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(--ntl-key-border-radius);
16
- padding: var(--ntl-key-padding-block, .05em) var(--ntl-key-padding-inline, .3em);
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,4 +1,4 @@
1
- import { h, ComponentChildren, Ref } from 'preact';
1
+ import { ComponentChildren, Ref } from 'preact';
2
2
  import { forwardRef } from 'preact/compat';
3
3
 
4
4
  interface Props {
@@ -0,0 +1,7 @@
1
+ .n-search-heading {
2
+ padding-inline: 1rem;
3
+ margin-block: var(--space-xs);
4
+ font-size: var(--step--2);
5
+ font-weight: var(--font-regular);
6
+ color: var(--color-text-3);
7
+ }
@@ -1,11 +1,13 @@
1
- import { h, type ComponentChildren } from 'preact';
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-results-heading">{children}</h2>;
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 extends h.JSX.HTMLAttributes<HTMLInputElement> {
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, content_type, url, excerpt }: Props) => {
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
- --ntl-search-padding-inline: .5em;
8
- --ntl-search-color-text: var(--color-text-2);
9
- --ntl-search-color-bg: var(--color-bg-1);
10
- --ntl-search-color-border: var(--color-bg-3);
11
- --ntl-search-border-radius: 8px;
12
- --ntl-search-max-w: 600px;
13
- --ntl-search-text-highlight: var(--color-text-accent);
14
- --ntl-search-footer-key-color-text: var(--color-text-2);
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(--ntl-search-text-highlight);
23
+ .n-search-container {
24
+ --mark-bg: var(--n-search-text-highlight);
20
25
  display: grid;
21
- width: min(var(--ntl-search-max-w), 100%);
26
+ width: min(var(--n-search-max-w), 100%);
22
27
  min-height: 470px;
23
- background-color: var(--ntl-search-color-bg);
24
- border-radius: var(--ntl-search-border-radius);
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(--ntl-search-color-bg);
43
- border-bottom: 1px solid var(--ntl-search-color-border);
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(--ntl-search-color-bg);
53
+ background: var(--n-search-color-bg);
74
54
  inline-size: 100%;
75
55
  padding-block: .75rem;
76
- padding-inline: var(--ntl-search-padding-inline);
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(--ntl-search-color-text);
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(--ntl-search-padding-inline);
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: lightgray;
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(--neutral-300);
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-results-heading {
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(--ntl-search-color-bg);
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(--ntl-result-padding-block, 1em) var(--ntl-result-padding-inline, 1rem);
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(--neutral-100);
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(--ntl-search-color-border);
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
- --ntl-key-text-color: var(--ntl-search-footer-key-color-text);
204
- color: var(--ntl-search-footer-key-color-text);
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;
@@ -1,4 +1,4 @@
1
- .search-toggle {
1
+ .n-search-toggle {
2
2
  all: unset;
3
3
  outline: revert;
4
4
  cursor: pointer;
@@ -8,6 +8,6 @@
8
8
  max-width: max-content;
9
9
  }
10
10
 
11
- .search-toggle:disabled {
11
+ .n-search-toggle:disabled {
12
12
  opacity: .3;
13
13
  }
@@ -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
- import { type ComponentChildren } from 'preact';
2
- import { useState, useEffect, useRef } from 'preact/hooks';
3
-
4
- import Modal from '../Modal';
5
- import { SearchFooter, SearchFooterTip, SearchInput, SearchWindow } from './components';
6
- import KeyboardKey from '../KeyboardKey';
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,4 +1,4 @@
1
- import type { ComponentChildren, FunctionComponent } from 'preact';
1
+ import type { ComponentChildren } from 'preact';
2
2
  import type { IconName } from '../../Icon';
3
3
 
4
4
  export interface ResultProps {
@@ -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 { default as SearchModal } from './SearchModal';
7
+ export { SearchModal } from './SearchModal';
8
8
 
9
9
  export { type IconName } from './Icon';