@netlify/spark-ui 0.0.46-alpha.2 → 0.0.46-alpha.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.
@@ -2,6 +2,7 @@ import { ComponentChildren } from 'preact';
2
2
  interface Props {
3
3
  children: ComponentChildren;
4
4
  className?: string;
5
+ debug?: boolean;
5
6
  }
6
7
  declare function SearchModal(props?: Props): import("preact").JSX.Element;
7
8
  export default SearchModal;
@@ -1,42 +1,42 @@
1
1
  import { u as e } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { A as v, y as u, d as g } from "../../../../../chunks/hooks.module.CNV9mxng.js";
3
- import T from "../../../Modal/Modal.js";
2
+ import { A as v, y as u, d as S } from "../../../../../chunks/hooks.module.CNV9mxng.js";
3
+ import L from "../../../Modal/Modal.js";
4
4
  import d from "../../../KeyboardKey/KeyboardKey.js";
5
- import L from "../SearchWindow.js";
6
- import k from "../SearchInput.js";
7
- import { useSearch as w } from "../../hooks/useSearch.js";
8
- import { useSearchLogger as I } from "../../hooks/useSearchLogger.js";
5
+ import k from "../SearchWindow.js";
6
+ import w from "../SearchInput.js";
7
+ import { useSearch as I } from "../../hooks/useSearch.js";
8
+ import { useSearchLogger as b } from "../../hooks/useSearchLogger.js";
9
9
  import { useKeyboardNav as O } from "../../hooks/useKeyboardNav.js";
10
10
  import { useSearchHotkeys as P } from "../../hooks/useSearchHotkeys.js";
11
11
  import { useSearchParams as E } from "../../hooks/useSearchParams.js";
12
12
  import { useSearchToggles as K } from "../../hooks/useSearchToggles.js";
13
- import '../../../../../assets/SearchModal.css';function M(s) {
13
+ import '../../../../../assets/SearchModal.css';function M(o) {
14
14
  const r = v(null);
15
15
  return u(() => {
16
16
  function t(i) {
17
- r.current && !r.current.contains(i.target) && s();
17
+ r.current && !r.current.contains(i.target) && o();
18
18
  }
19
19
  return document.addEventListener("mousedown", t), () => {
20
20
  document.removeEventListener("mousedown", t);
21
21
  };
22
- }, [s]), r;
22
+ }, [o]), r;
23
23
  }
24
- function z(s = { className: "", children: null }) {
25
- const [r, t] = g(!1);
24
+ function B(o = { className: "", children: null, debug: !1 }) {
25
+ const [r, t] = S(!1);
26
26
  u(() => {
27
27
  let c;
28
- const S = () => {
28
+ const g = () => {
29
29
  window.pagefind && (t(!0), c && clearInterval(c));
30
30
  };
31
- return S(), c = setInterval(S, 100), () => clearInterval(c);
31
+ return g(), c = setInterval(g, 100), () => clearInterval(c);
32
32
  }, []);
33
- const { children: i, className: f, ...N } = s, { state: a, actions: h } = w(), [n, p] = g(!1), m = () => p(!0), l = () => p(!1), o = v(null), y = M(l);
34
- return I(a), K(r, m), E(r, h.setSearchTerm, m), P(r, n, m, l), O(r, o, n, l), u(() => {
35
- o.current && (n ? o.current.showModal() : o.current.close());
36
- }, [n]), /* @__PURE__ */ e(T, { ref: o, className: `n-search-modal ${f || ""}`, ...N, children: /* @__PURE__ */ e("div", { ref: y, className: "n-search-container", children: [
37
- /* @__PURE__ */ e(k, { setSearchTerm: h.setSearchTerm, initialValue: a.searchTerm }),
33
+ const { children: i, className: f, debug: N, ...y } = o, { state: a, actions: h } = I(), [n, p] = S(!1), m = () => p(!0), l = () => p(!1), s = v(null), T = M(l);
34
+ return b(a, N), K(r, m), E(r, h.setSearchTerm, m), P(r, n, m, l), O(r, s, n, l), u(() => {
35
+ s.current && (n ? s.current.showModal() : s.current.close());
36
+ }, [n]), /* @__PURE__ */ e(L, { ref: s, className: `n-search-modal ${f || ""}`, ...y, children: /* @__PURE__ */ e("div", { ref: T, className: "n-search-container", children: [
37
+ /* @__PURE__ */ e(w, { setSearchTerm: h.setSearchTerm, initialValue: a.searchTerm }),
38
38
  /* @__PURE__ */ e(
39
- L,
39
+ k,
40
40
  {
41
41
  searchLoading: a.isLoading,
42
42
  searchTerm: a.searchTerm,
@@ -59,5 +59,5 @@ function z(s = { className: "", children: null }) {
59
59
  ] }) });
60
60
  }
61
61
  export {
62
- z as default
62
+ B as default
63
63
  };
@@ -12,6 +12,7 @@ import { SearchState } from '../types/search.types';
12
12
  * @param {SearchState} [state] - The search state, which includes the current search term and the results of the search.
13
13
  * - `state.searchTerm`: The current search query string.
14
14
  * - `state.results`: The search results array. If it's empty, the hook will log a no-results event.
15
+ * @param {boolean} [debug=false] - Flag to enable debug mode. If true, additional debug information will be sent with the event payloads.
15
16
  *
16
17
  * @returns {Object} - An object with the following function:
17
18
  * - `handleClick`: A callback function that should be attached to search result click events. It tracks `spark_search:result_clicked` events with the clicked result's title and URL.
@@ -22,6 +23,6 @@ import { SearchState } from '../types/search.types';
22
23
  * // In your component, attach handleClick to the search result links
23
24
  * <a href="result-url" onClick={handleClick}>Search Result</a>
24
25
  */
25
- export declare function useSearchLogger(state?: SearchState): {
26
+ export declare function useSearchLogger(state?: SearchState, debug?: boolean): {
26
27
  handleClick: (e: Event) => void;
27
28
  };
@@ -1,33 +1,37 @@
1
- import { A as k, y as u, q as f } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
- class g {
1
+ import { A as k, y as h, q as m } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
+ class y {
3
3
  /**
4
4
  * Pushes an event payload into the dataLayer.
5
5
  * @param eventName e.g. 'www:search_query_changed'
6
6
  * @param payload additional key/value data
7
7
  */
8
- track(n, c = {}) {
9
- gtag("event", n, { ...c });
8
+ track(l, u = {}) {
9
+ gtag("event", l, { ...u });
10
10
  }
11
11
  }
12
- function T(r) {
13
- const c = k(new g()).current;
14
- return u(() => {
15
- r != null && r.searchTerm && c.track("spark_search:query_changed", { query: r == null ? void 0 : r.searchTerm });
16
- }, [r == null ? void 0 : r.searchTerm]), u(() => {
17
- r != null && r.results && r != null && r.searchTerm && r.results.length === 0 && c.track("spark_search:no_results", { query: r == null ? void 0 : r.searchTerm });
12
+ function p(r, l) {
13
+ const n = k(new y()).current;
14
+ return h(() => {
15
+ if (!(r != null && r.searchTerm)) return;
16
+ const c = { query: r == null ? void 0 : r.searchTerm };
17
+ l && (c.debug_mode = !0), n.track("spark_search:query_changed", c);
18
+ }, [r == null ? void 0 : r.searchTerm]), h(() => {
19
+ if (!(r != null && r.results)) return;
20
+ const c = { query: r == null ? void 0 : r.searchTerm };
21
+ l && (c.debug_mode = !0), r != null && r.searchTerm && r.results.length === 0 && n.track("spark_search:no_results", c);
18
22
  }, [r == null ? void 0 : r.results]), {
19
- handleClick: f((h) => {
20
- var e;
21
- const l = h.target.closest("a");
22
- if (!l) return;
23
- const i = (e = l.querySelector(".n-search-link-label")) == null ? void 0 : e.innerHTML, o = l.getAttribute("href");
24
- c.track("spark_search:result_clicked", {
25
- resultTitle: i,
26
- resultUrl: o
27
- });
23
+ handleClick: m((c) => {
24
+ var i;
25
+ const e = c.target.closest("a");
26
+ if (!e) return;
27
+ const d = (i = e.querySelector(".n-search-link-label")) == null ? void 0 : i.innerHTML, f = e.getAttribute("href"), o = {
28
+ resultTitle: d,
29
+ resultUrl: f
30
+ };
31
+ l && (o.debug_mode = !0), n.track("spark_search:result_clicked", o);
28
32
  }, [])
29
33
  };
30
34
  }
31
35
  export {
32
- T as useSearchLogger
36
+ p as useSearchLogger
33
37
  };
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.46-alpha.2",
4
+ "version": "0.0.46-alpha.3",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -20,9 +20,10 @@ import './SearchModal.css';
20
20
  interface Props {
21
21
  children: ComponentChildren;
22
22
  className?: string;
23
+ debug?: boolean
23
24
  }
24
25
 
25
- function SearchModal(props: Props = {className: '', children: null}) {
26
+ function SearchModal(props: Props = {className: '', children: null, debug: false }) {
26
27
  const [isPagefindLoaded, setIsPagefindLoaded] = useState(false);
27
28
 
28
29
  // Poll for the existence of window.pagefind.
@@ -45,7 +46,7 @@ function SearchModal(props: Props = {className: '', children: null}) {
45
46
  }, []);
46
47
 
47
48
 
48
- const { children, className, ...rest } = props;
49
+ const { children, className, debug, ...rest } = props;
49
50
  const { state, actions } = useSearch();
50
51
  const [searchOpen, setSearchOpen] = useState(false);
51
52
 
@@ -55,7 +56,7 @@ function SearchModal(props: Props = {className: '', children: null}) {
55
56
  const modalRef = useRef<HTMLDialogElement>(null);
56
57
  const containerRef = useClickOutside<HTMLDivElement>(closeSearch);
57
58
 
58
- useSearchLogger(state)
59
+ useSearchLogger(state, debug)
59
60
  useSearchToggles(isPagefindLoaded, openSearch);
60
61
  useSearchParams(isPagefindLoaded, actions.setSearchTerm, openSearch);
61
62
  useSearchHotkeys(isPagefindLoaded, searchOpen, openSearch, closeSearch);
@@ -15,52 +15,69 @@ import Analytics from '../../../../analytics/analytics';
15
15
  * @param {SearchState} [state] - The search state, which includes the current search term and the results of the search.
16
16
  * - `state.searchTerm`: The current search query string.
17
17
  * - `state.results`: The search results array. If it's empty, the hook will log a no-results event.
18
- *
18
+ * @param {boolean} [debug=false] - Flag to enable debug mode. If true, additional debug information will be sent with the event payloads.
19
+ *
19
20
  * @returns {Object} - An object with the following function:
20
21
  * - `handleClick`: A callback function that should be attached to search result click events. It tracks `spark_search:result_clicked` events with the clicked result's title and URL.
21
22
  *
22
23
  * @example
23
24
  * const { handleClick } = useSearchLogger(searchState);
24
- *
25
+ *
25
26
  * // In your component, attach handleClick to the search result links
26
27
  * <a href="result-url" onClick={handleClick}>Search Result</a>
27
28
  */
28
29
 
29
- export function useSearchLogger(state?: SearchState) {
30
+ export function useSearchLogger(state?: SearchState, debug?: boolean) {
30
31
  const ref = useRef<Analytics>(new Analytics());
31
32
  const analytics = ref.current;
32
33
 
33
34
  // Log search query
34
35
  useEffect(() => {
35
- if (!state?.searchTerm) return
36
- analytics.track('spark_search:query_changed', { query: state?.searchTerm });
36
+ if (!state?.searchTerm) return;
37
+ const payload = { query: state?.searchTerm };
38
+
39
+ if (debug) {
40
+ payload.debug_mode = true;
41
+ }
42
+
43
+ analytics.track('spark_search:query_changed', payload);
37
44
  }, [state?.searchTerm]);
38
45
 
39
46
  // Log zero‑hit searches
40
47
  useEffect(() => {
41
- if (!state?.results) return
48
+ if (!state?.results) return;
49
+
50
+ const payload = { query: state?.searchTerm };
51
+
52
+ if (debug) {
53
+ payload.debug_mode = true;
54
+ }
42
55
 
43
56
  if (state?.searchTerm && state.results.length === 0) {
44
- analytics.track('spark_search:no_results', { query: state?.searchTerm });
57
+ analytics.track('spark_search:no_results', payload);
45
58
  }
46
59
  }, [state?.results]);
47
60
 
48
61
  const handleResultClick = useCallback((e: Event) => {
49
62
  const anchor = (e.target as HTMLElement).closest('a');
50
-
51
- if (!anchor) return
52
63
 
53
- const label = anchor.querySelector('.n-search-link-label')?.innerHTML
54
- const url = anchor.getAttribute('href')
64
+ if (!anchor) return;
55
65
 
56
- analytics.track('spark_search:result_clicked', {
66
+ const label = anchor.querySelector('.n-search-link-label')?.innerHTML;
67
+ const url = anchor.getAttribute('href');
68
+ const payload = {
57
69
  resultTitle: label,
58
70
  resultUrl: url,
59
- });
60
- }, []);
71
+ };
61
72
 
73
+ if (debug) {
74
+ payload.debug_mode = true;
75
+ }
76
+
77
+ analytics.track('spark_search:result_clicked', payload);
78
+ }, []);
62
79
 
63
80
  return {
64
- handleClick: handleResultClick
81
+ handleClick: handleResultClick,
65
82
  };
66
83
  }