@netlify/spark-ui 0.0.24 → 0.0.26

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.
@@ -1,98 +1,106 @@
1
- import { u as s } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { A as h, y as S, d as v } from "../../../../../chunks/hooks.module.BFfOesdf.js";
3
- import N from "../../../Modal/Modal.js";
4
- import f from "../../../KeyboardKey/KeyboardKey.js";
5
- import O from "../SearchWindow.js";
6
- import T from "../SearchInput.js";
7
- import { useSearch as b } from "../../hooks/useSearch.js";
8
- import { useKeyboardNav as w } from "../../hooks/useKeyboardNav.js";
1
+ import { u as n } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
+ import { A as O, y as v, d as N } from "../../../../../chunks/hooks.module.BFfOesdf.js";
3
+ import T from "../../../Modal/Modal.js";
4
+ import p from "../../../KeyboardKey/KeyboardKey.js";
5
+ import b from "../SearchWindow.js";
6
+ import I from "../SearchInput.js";
7
+ import { useSearch as L } from "../../hooks/useSearch.js";
8
+ import { useKeyboardNav as P } from "../../hooks/useKeyboardNav.js";
9
9
  import { useSearchHotkeys as E } from "../../hooks/useSearchHotkeys.js";
10
- import { useSearchParams as g } from "../../hooks/useSearchParams.js";
11
- import { useSearchToggles as j } from "../../hooks/useSearchToggles.js";
10
+ import { useSearchParams as j } from "../../hooks/useSearchParams.js";
11
+ import { useSearchToggles as k } from "../../hooks/useSearchToggles.js";
12
12
  import '../../../../../assets/SearchModal.css';function x(t) {
13
13
  return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
14
14
  }
15
- var p = { exports: {} };
15
+ var h = { exports: {} };
16
16
  /*!
17
17
  Copyright (c) 2018 Jed Watson.
18
18
  Licensed under the MIT License (MIT), see
19
19
  http://jedwatson.github.io/classnames
20
20
  */
21
- var d;
21
+ var w;
22
22
  function C() {
23
- return d || (d = 1, function(t) {
23
+ return w || (w = 1, function(t) {
24
24
  (function() {
25
- var a = {}.hasOwnProperty;
26
- function n() {
25
+ var s = {}.hasOwnProperty;
26
+ function o() {
27
27
  for (var e = "", r = 0; r < arguments.length; r++) {
28
- var o = arguments[r];
29
- o && (e = c(e, i(o)));
28
+ var a = arguments[r];
29
+ a && (e = l(e, c(a)));
30
30
  }
31
31
  return e;
32
32
  }
33
- function i(e) {
33
+ function c(e) {
34
34
  if (typeof e == "string" || typeof e == "number")
35
35
  return e;
36
36
  if (typeof e != "object")
37
37
  return "";
38
38
  if (Array.isArray(e))
39
- return n.apply(null, e);
39
+ return o.apply(null, e);
40
40
  if (e.toString !== Object.prototype.toString && !e.toString.toString().includes("[native code]"))
41
41
  return e.toString();
42
42
  var r = "";
43
- for (var o in e)
44
- a.call(e, o) && e[o] && (r = c(r, o));
43
+ for (var a in e)
44
+ s.call(e, a) && e[a] && (r = l(r, a));
45
45
  return r;
46
46
  }
47
- function c(e, r) {
47
+ function l(e, r) {
48
48
  return r ? e ? e + " " + r : e + r : e;
49
49
  }
50
- t.exports ? (n.default = n, t.exports = n) : window.classNames = n;
50
+ t.exports ? (o.default = o, t.exports = o) : window.classNames = o;
51
51
  })();
52
- }(p)), p.exports;
52
+ }(h)), h.exports;
53
53
  }
54
- var L = C();
55
- const M = /* @__PURE__ */ x(L);
56
- function k(t) {
57
- const a = h(null);
58
- return S(() => {
59
- function n(i) {
60
- a.current && !a.current.contains(i.target) && t();
54
+ var M = C();
55
+ const A = /* @__PURE__ */ x(M);
56
+ function K(t) {
57
+ const s = O(null);
58
+ return v(() => {
59
+ function o(c) {
60
+ s.current && !s.current.contains(c.target) && t();
61
61
  }
62
- return document.addEventListener("mousedown", n), () => {
63
- document.removeEventListener("mousedown", n);
62
+ return document.addEventListener("mousedown", o), () => {
63
+ document.removeEventListener("mousedown", o);
64
64
  };
65
- }, [t]), a;
65
+ }, [t]), s;
66
66
  }
67
- function W(t = { className: "", children: null }) {
68
- const { children: a, className: n, ...i } = t, { state: c, actions: e } = b(), [r, o] = v(!1), l = () => o(!0), m = () => o(!1), u = h(null), y = k(m);
69
- return j(l), g(e.setSearchTerm, l), E(r, l, m), w(u, r, m), S(() => {
70
- u.current && (r ? u.current.showModal() : u.current.close());
71
- }, [r]), /* @__PURE__ */ s(N, { ref: u, className: M(n, "n-search-modal"), ...i, children: /* @__PURE__ */ s("div", { ref: y, className: "n-search-container", children: [
72
- /* @__PURE__ */ s("form", { className: "n-search-bar", children: /* @__PURE__ */ s(T, { setSearchTerm: e.setSearchTerm, initialValue: c.searchTerm }) }),
73
- /* @__PURE__ */ s(
74
- O,
67
+ function J(t = { className: "", children: null }) {
68
+ const [s, o] = N(!1);
69
+ v(() => {
70
+ let f;
71
+ const y = () => {
72
+ window.pagefind && (o(!0), f && clearInterval(f));
73
+ };
74
+ return y(), f = setInterval(y, 100), () => clearInterval(f);
75
+ }, []);
76
+ const { children: c, className: l, ...e } = t, { state: r, actions: a } = L(), [u, S] = N(!1), m = () => S(!0), d = () => S(!1), i = O(null), g = K(d);
77
+ return k(s, m), j(s, a.setSearchTerm, m), E(s, u, m, d), P(s, i, u, d), v(() => {
78
+ i.current && (u ? i.current.showModal() : i.current.close());
79
+ }, [u]), /* @__PURE__ */ n(T, { ref: i, className: A(l, "n-search-modal"), ...e, children: /* @__PURE__ */ n("div", { ref: g, className: "n-search-container", children: [
80
+ /* @__PURE__ */ n(I, { setSearchTerm: a.setSearchTerm, initialValue: r.searchTerm }),
81
+ /* @__PURE__ */ n(
82
+ b,
75
83
  {
76
- searchLoading: c.isLoading,
77
- searchTerm: c.searchTerm,
78
- results: c.results,
79
- children: a
84
+ searchLoading: r.isLoading,
85
+ searchTerm: r.searchTerm,
86
+ results: r.results,
87
+ children: c
80
88
  }
81
89
  ),
82
- /* @__PURE__ */ s("div", { className: "n-search-footer", children: [
83
- /* @__PURE__ */ s("p", { className: "n-search-footer-tip", children: [
84
- /* @__PURE__ */ s(f, { keyNames: ["Esc"] }),
90
+ /* @__PURE__ */ n("div", { className: "n-search-footer", children: [
91
+ /* @__PURE__ */ n("p", { className: "n-search-footer-tip", children: [
92
+ /* @__PURE__ */ n(p, { keyNames: ["Esc"] }),
85
93
  "to close"
86
94
  ] }),
87
- /* @__PURE__ */ s("p", { className: "n-search-footer-tip", children: [
88
- /* @__PURE__ */ s(f, { keyNames: ["Tab"] }),
89
- /* @__PURE__ */ s("span", { children: "or" }),
90
- /* @__PURE__ */ s(f, { keyNames: ["↑", "↓"] }),
95
+ /* @__PURE__ */ n("p", { className: "n-search-footer-tip", children: [
96
+ /* @__PURE__ */ n(p, { keyNames: ["Tab"] }),
97
+ /* @__PURE__ */ n("span", { children: "or" }),
98
+ /* @__PURE__ */ n(p, { keyNames: ["↑", "↓"] }),
91
99
  "to navigate"
92
100
  ] })
93
101
  ] })
94
102
  ] }) });
95
103
  }
96
104
  export {
97
- W as default
105
+ J as default
98
106
  };
@@ -11,4 +11,4 @@ import { RefObject } from 'preact';
11
11
  * @param isOpen - Boolean indicating whether the navigation context is active
12
12
  * @param onClose - Callback to close the navigation UI when `Escape` is pressed
13
13
  */
14
- export declare function useKeyboardNav(containerRef: RefObject<HTMLElement>, isOpen: boolean, onClose: () => void): void;
14
+ export declare function useKeyboardNav(isPagefindLoaded: boolean, containerRef: RefObject<HTMLElement>, isOpen: boolean, onClose: () => void): void;
@@ -1,24 +1,25 @@
1
- import { y as a } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
- function l(r, t, o) {
3
- a(() => {
4
- const c = (e) => {
5
- if (t) {
1
+ import { y as l } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
+ function s(r, t, o, c) {
3
+ l(() => {
4
+ if (!r) return;
5
+ const u = (e) => {
6
+ if (o) {
6
7
  if (e.key === "Escape") {
7
- o();
8
+ c();
8
9
  return;
9
10
  }
10
11
  if (e.key === "ArrowUp" || e.key === "ArrowDown") {
11
12
  e.preventDefault();
12
- const d = r.current;
13
+ const d = t.current;
13
14
  if (!d) return;
14
- const n = Array.from(d.querySelectorAll("a")), u = n.findIndex((i) => i === document.activeElement), y = e.key === "ArrowDown" ? (u + 1) % n.length : (u - 1 + n.length) % n.length;
15
- n[y].focus();
15
+ const n = Array.from(d.querySelectorAll("a")), y = n.findIndex((i) => i === document.activeElement), f = e.key === "ArrowDown" ? (y + 1) % n.length : (y - 1 + n.length) % n.length;
16
+ n[f].focus();
16
17
  }
17
18
  }
18
19
  };
19
- return document.addEventListener("keydown", c), () => document.removeEventListener("keydown", c);
20
- }, [r, t, o]);
20
+ return document.addEventListener("keydown", u), () => document.removeEventListener("keydown", u);
21
+ }, [r, t, o, c]);
21
22
  }
22
23
  export {
23
- l as useKeyboardNav
24
+ s as useKeyboardNav
24
25
  };
@@ -10,4 +10,4 @@
10
10
  * @param onOpen - Callback to open the search interface.
11
11
  * @param onClose - Callback to close the search interface.
12
12
  */
13
- export declare function useSearchHotkeys(isOpen: boolean, onOpen: () => void, onClose: () => void): void;
13
+ export declare function useSearchHotkeys(isPagefindLoaded: boolean, isOpen: boolean, onOpen: () => void, onClose: () => void): void;
@@ -1,12 +1,13 @@
1
- import { y as d } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
- function m(t, n, o) {
3
- d(() => {
4
- const r = (e) => {
5
- e.metaKey && e.key === "k" && (e.preventDefault(), e.stopImmediatePropagation(), t ? o() : n());
1
+ import { y as u } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
+ function a(t, r, n, o) {
3
+ u(() => {
4
+ if (!t) return;
5
+ const m = (e) => {
6
+ e.metaKey && e.key === "k" && (e.preventDefault(), e.stopImmediatePropagation(), r ? o() : n());
6
7
  };
7
- return document.addEventListener("keydown", r), () => document.removeEventListener("keydown", r);
8
- }, [t, n, o]);
8
+ return document.addEventListener("keydown", m), () => document.removeEventListener("keydown", m);
9
+ }, [t, r, n, o]);
9
10
  }
10
11
  export {
11
- m as useSearchHotkeys
12
+ a as useSearchHotkeys
12
13
  };
@@ -8,4 +8,4 @@
8
8
  * @param setSearchTerm - Function to update the search input state.
9
9
  * @param onOpen - Function to trigger opening of the search interface (e.g., modal or drawer).
10
10
  */
11
- export declare function useSearchParams(setSearchTerm: (term: string) => void, onOpen: () => void): void;
11
+ export declare function useSearchParams(isPagefindLoaded: boolean, setSearchTerm: (term: string) => void, onOpen: () => void): void;
@@ -1,11 +1,11 @@
1
- import { y as e } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
- function t(a, o) {
3
- e(() => {
4
- if (typeof location > "u") return;
5
- const r = (location == null ? void 0 : location.search) && new URLSearchParams(location.search).get("search");
6
- r && (a(r), o());
7
- }, [a, o]);
1
+ import { y as c } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
+ function n(r, o, a) {
3
+ c(() => {
4
+ if (typeof location > "u" || r) return;
5
+ const e = (location == null ? void 0 : location.search) && new URLSearchParams(location.search).get("search");
6
+ e && (o(e), a());
7
+ }, [r]);
8
8
  }
9
9
  export {
10
- t as useSearchParams
10
+ n as useSearchParams
11
11
  };
@@ -9,4 +9,4 @@
9
9
  *
10
10
  * @param onOpen - A function to be called when a toggle element is clicked.
11
11
  */
12
- export declare function useSearchToggles(onOpen: () => void): void;
12
+ export declare function useSearchToggles(isPagefindLoaded: boolean, onOpen: () => void): void;
@@ -1,15 +1,16 @@
1
- import { y as c } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
- function l(t) {
3
- c(() => {
4
- const r = document.querySelectorAll("[data-ntl-search-toggle]");
5
- if (r.length)
6
- return r.forEach((e) => {
7
- e.removeAttribute("disabled"), e.addEventListener("click", t);
1
+ import { y as l } from "../../../../chunks/hooks.module.BFfOesdf.js";
2
+ function i(c, r) {
3
+ l(() => {
4
+ if (!c) return;
5
+ const t = document.querySelectorAll("[data-ntl-search-toggle]");
6
+ if (t.length)
7
+ return t.forEach((e) => {
8
+ e.removeAttribute("disabled"), e.addEventListener("click", r);
8
9
  }), () => {
9
- r.forEach((e) => e.removeEventListener("click", t));
10
+ t.forEach((e) => e.removeEventListener("click", r));
10
11
  };
11
- }, [t]);
12
+ }, [c, r]);
12
13
  }
13
14
  export {
14
- l as useSearchToggles
15
+ i as useSearchToggles
15
16
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/spark-ui",
3
3
  "description": "Assets, design tokens, components, and utilities",
4
- "version": "0.0.24",
4
+ "version": "0.0.26",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -2,11 +2,11 @@ import { type ComponentChildren } from 'preact';
2
2
  import { useState, useEffect, useRef } from 'preact/hooks';
3
3
  import cn from "classnames"
4
4
 
5
- import Modal from '@components/preact/Modal/Modal';
6
- import KeyboardKey from '@components/preact/KeyboardKey/KeyboardKey';
5
+ import Modal from '../../../../preact/Modal/Modal';
6
+ import KeyboardKey from '../../../../preact/KeyboardKey/KeyboardKey';
7
7
  import SearchWindow from '../../components/SearchWindow';
8
8
  import SearchInput from '../../components/SearchInput';
9
- import { useClickOutside } from '@utils/useClickOutside';
9
+ import { useClickOutside } from '../../../../../utils/useClickOutside';
10
10
  import {
11
11
  useSearch,
12
12
  useKeyboardNav,
@@ -23,6 +23,28 @@ interface Props {
23
23
  }
24
24
 
25
25
  function SearchModal(props: Props = {className: '', children: null}) {
26
+ const [isPagefindLoaded, setIsPagefindLoaded] = useState(false);
27
+
28
+ // Poll for the existence of window.pagefind.
29
+ useEffect(() => {
30
+ let intervalId:number;
31
+
32
+ const checkForPagefind = () => {
33
+ if (window.pagefind) {
34
+ setIsPagefindLoaded(true);
35
+ if (intervalId) clearInterval(intervalId);
36
+ }
37
+ };
38
+
39
+ // Check immediately and then start polling every 100ms.
40
+ checkForPagefind();
41
+ intervalId = setInterval(checkForPagefind, 100);
42
+
43
+ // Cleanup the interval when the component unmounts.
44
+ return () => clearInterval(intervalId);
45
+ }, []);
46
+
47
+
26
48
  const { children, className, ...rest } = props;
27
49
  const { state, actions } = useSearch();
28
50
  const [searchOpen, setSearchOpen] = useState(false);
@@ -33,10 +55,10 @@ function SearchModal(props: Props = {className: '', children: null}) {
33
55
  const modalRef = useRef<HTMLDialogElement>(null);
34
56
  const containerRef = useClickOutside<HTMLDivElement>(closeSearch);
35
57
 
36
- useSearchToggles(openSearch);
37
- useSearchParams(actions.setSearchTerm, openSearch);
38
- useSearchHotkeys(searchOpen, openSearch, closeSearch);
39
- useKeyboardNav(modalRef, searchOpen, closeSearch);
58
+ useSearchToggles(isPagefindLoaded, openSearch);
59
+ useSearchParams(isPagefindLoaded, actions.setSearchTerm, openSearch);
60
+ useSearchHotkeys(isPagefindLoaded, searchOpen, openSearch, closeSearch);
61
+ useKeyboardNav(isPagefindLoaded, modalRef, searchOpen, closeSearch);
40
62
 
41
63
  useEffect(() => {
42
64
  if (!modalRef.current) return;
@@ -46,9 +68,7 @@ function SearchModal(props: Props = {className: '', children: null}) {
46
68
  return (
47
69
  <Modal ref={modalRef} className={cn(className, 'n-search-modal')} {...rest}>
48
70
  <div ref={containerRef} className="n-search-container">
49
- <form className="n-search-bar">
50
71
  <SearchInput setSearchTerm={actions.setSearchTerm} initialValue={state.searchTerm} />
51
- </form>
52
72
 
53
73
  <SearchWindow
54
74
  searchLoading={state.isLoading}
@@ -15,11 +15,13 @@ import { useEffect } from 'preact/hooks';
15
15
  */
16
16
 
17
17
  export function useKeyboardNav(
18
+ isPagefindLoaded: boolean,
18
19
  containerRef: RefObject<HTMLElement>,
19
20
  isOpen: boolean,
20
21
  onClose: () => void
21
22
  ) {
22
23
  useEffect(() => {
24
+ if (!isPagefindLoaded) return
23
25
  const handleKeydown = (e: KeyboardEvent) => {
24
26
  if (!isOpen) return;
25
27
 
@@ -46,5 +48,5 @@ export function useKeyboardNav(
46
48
 
47
49
  document.addEventListener('keydown', handleKeydown);
48
50
  return () => document.removeEventListener('keydown', handleKeydown);
49
- }, [containerRef, isOpen, onClose]);
51
+ }, [isPagefindLoaded, containerRef, isOpen, onClose]);
50
52
  }
@@ -30,7 +30,6 @@ export function useSearch() {
30
30
  const submitSearch = async (query: string) => {
31
31
  if (!window?.pagefind) return;
32
32
 
33
-
34
33
  setSearchState(prev => ({ ...prev, isLoading: true }));
35
34
 
36
35
  if (cacheRef.current.has(query)) {
@@ -13,8 +13,10 @@ import { useEffect } from 'preact/hooks';
13
13
  * @param onClose - Callback to close the search interface.
14
14
  */
15
15
 
16
- export function useSearchHotkeys(isOpen: boolean, onOpen: () => void, onClose: () => void) {
16
+ export function useSearchHotkeys(isPagefindLoaded: boolean, isOpen: boolean, onOpen: () => void, onClose: () => void) {
17
17
  useEffect(() => {
18
+ if (!isPagefindLoaded) return;
19
+
18
20
  const handleKeydown = (e: KeyboardEvent) => {
19
21
  if (e.metaKey && e.key === 'k') {
20
22
  e.preventDefault();
@@ -25,5 +27,5 @@ export function useSearchHotkeys(isOpen: boolean, onOpen: () => void, onClose: (
25
27
 
26
28
  document.addEventListener('keydown', handleKeydown);
27
29
  return () => document.removeEventListener('keydown', handleKeydown);
28
- }, [isOpen, onOpen, onClose]);
30
+ }, [isPagefindLoaded, isOpen, onOpen, onClose]);
29
31
  }
@@ -11,13 +11,13 @@ import { useEffect } from 'preact/hooks';
11
11
  * @param onOpen - Function to trigger opening of the search interface (e.g., modal or drawer).
12
12
  */
13
13
 
14
- export function useSearchParams(setSearchTerm: (term: string) => void, onOpen: () => void) {
14
+ export function useSearchParams(isPagefindLoaded: boolean, setSearchTerm: (term: string) => void, onOpen: () => void) {
15
15
  useEffect(() => {
16
- if (typeof location === 'undefined') return;
16
+ if (typeof location === 'undefined' || isPagefindLoaded) return;
17
17
  const query = location?.search && new URLSearchParams(location.search).get('search');
18
18
  if (query) {
19
19
  setSearchTerm(query);
20
20
  onOpen();
21
21
  }
22
- }, [setSearchTerm, onOpen]);
22
+ }, [isPagefindLoaded]);
23
23
  }
@@ -12,8 +12,9 @@ import { useEffect } from 'preact/hooks';
12
12
  * @param onOpen - A function to be called when a toggle element is clicked.
13
13
  */
14
14
 
15
- export function useSearchToggles(onOpen: () => void) {
15
+ export function useSearchToggles(isPagefindLoaded: boolean, onOpen: () => void) {
16
16
  useEffect(() => {
17
+ if (!isPagefindLoaded) return
17
18
  const toggles = document.querySelectorAll('[data-ntl-search-toggle]');
18
19
 
19
20
  if (!toggles.length) return;
@@ -26,5 +27,5 @@ export function useSearchToggles(onOpen: () => void) {
26
27
  return () => {
27
28
  toggles.forEach(t => t.removeEventListener('click', onOpen));
28
29
  };
29
- }, [onOpen]);
30
+ }, [isPagefindLoaded, onOpen]);
30
31
  }