@netlify/spark-ui 1.14.0 → 1.14.1

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,7 +2,8 @@ interface Props {
2
2
  setModalState?: (e: {
3
3
  current: string;
4
4
  }) => void;
5
- initialQuery?: string;
5
+ searchQuery?: string;
6
+ urlParamQuery?: string;
6
7
  }
7
- export default function AskNetlify({ setModalState, initialQuery }: Props): import("preact").JSX.Element;
8
+ export default function AskNetlify({ setModalState, searchQuery, urlParamQuery }: Props): import("preact").JSX.Element;
8
9
  export {};
@@ -1,6 +1,6 @@
1
1
  import "../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
2
  import "../../../chunks/hooks.module.DGkdD5n9.js";
3
- import { A as d } from "../../../chunks/AskNetlify.hLTCaFLd.js";
3
+ import { A as d } from "../../../chunks/AskNetlify.WwftmboN.js";
4
4
  import "./components/QuestionList/questions.js";
5
5
  import "./components/QuestionList/QuestionList.js";
6
6
  import "./components/BackButton.js";
@@ -1,83 +1,90 @@
1
1
  import { u as e } from "../../../../../chunks/jsxRuntime.module.Bzuv3cXw.js";
2
- import { A as g, y as h, d as k } from "../../../../../chunks/hooks.module.DGkdD5n9.js";
3
- import { A as w, K as b } from "../../../../../chunks/AskNetlify.hLTCaFLd.js";
4
- import K from "../../../Modal/Modal.js";
5
- import d from "../../../KeyboardKey/KeyboardKey.js";
6
- import L from "../SearchWindow.js";
7
- import M from "../SearchInput.js";
8
- import O from "../AskNetlifyLink.js";
2
+ import { A as g, y as f, d } from "../../../../../chunks/hooks.module.DGkdD5n9.js";
3
+ import { A as K, K as L } from "../../../../../chunks/AskNetlify.WwftmboN.js";
4
+ import P from "../../../Modal/Modal.js";
5
+ import h from "../../../KeyboardKey/KeyboardKey.js";
6
+ import M from "../SearchWindow.js";
7
+ import O from "../SearchInput.js";
8
+ import Q from "../AskNetlifyLink.js";
9
9
  import { useSearch as C } from "../../hooks/useSearch.js";
10
10
  import { useSearchAnalytics as E } from "../../hooks/useSearchAnalytics.js";
11
- import { useKeyboardNav as Q } from "../../hooks/useKeyboardNav.js";
12
- import { useSearchHotkeys as P } from "../../hooks/useSearchHotkeys.js";
13
- import { useSearchParams as R } from "../../hooks/useSearchParams.js";
14
- import { useSearchToggles as q } from "../../hooks/useSearchToggles.js";
15
- import { useAskAnalytics as x } from "../../../AskNetlify/hooks/useAskAnalytics.js";
11
+ import { useKeyboardNav as R } from "../../hooks/useKeyboardNav.js";
12
+ import { useSearchHotkeys as q } from "../../hooks/useSearchHotkeys.js";
13
+ import { useSearchParams as x } from "../../hooks/useSearchParams.js";
14
+ import { useSearchToggles as D } from "../../hooks/useSearchToggles.js";
15
+ import { useAskAnalytics as F } from "../../../AskNetlify/hooks/useAskAnalytics.js";
16
16
  import { Fragment as N } from "preact";
17
- import '../../../../../assets/SearchModal.css';function D(t) {
17
+ import '../../../../../assets/SearchModal.css';function G(a) {
18
18
  const n = g(null);
19
- return h(() => {
20
- function o(m) {
21
- n.current && !n.current.contains(m.target) && t();
19
+ return f(() => {
20
+ function s(m) {
21
+ n.current && !n.current.contains(m.target) && a();
22
22
  }
23
- return document.addEventListener("mousedown", o), () => {
24
- document.removeEventListener("mousedown", o);
23
+ return document.addEventListener("mousedown", s), () => {
24
+ document.removeEventListener("mousedown", s);
25
25
  };
26
- }, [t]), n;
26
+ }, [a]), n;
27
27
  }
28
- function re(t = { className: "", children: void 0, debug: !1, kapaIntegrationId: void 0 }) {
29
- const { children: n, className: o, debug: m, ...T } = t, [c, s] = k({ current: "search" }), [i, f] = k(!1), l = () => f(!0), u = () => f(!1), a = g(null), v = D(u), { state: r, actions: p } = C();
30
- q(l, s), R(l, p.setSearchTerm, s), P(i, l, u), Q(a, i, u), E(r, m);
31
- const { handleNewQuery: A, handleAnswer: I } = x();
32
- return h(() => {
33
- a.current && (i ? a.current.showModal() : a.current.close());
34
- }, [i]), h(() => {
35
- var y;
36
- const S = (y = a.current) == null ? void 0 : y.querySelector("input");
37
- S && S.focus();
28
+ function te(a = { className: "", children: void 0, debug: !1, kapaIntegrationId: void 0 }) {
29
+ const { children: n, className: s, debug: m, ...T } = a, [c, o] = d({ current: "search" }), [i, p] = d(!1), [v, A] = d(""), l = () => p(!0), u = () => p(!1), t = g(null), I = G(u), { state: r, actions: S } = C();
30
+ D(l, o), x(l, S.setSearchTerm, A, o), q(i, l, u), R(t, i, u), E(r, m);
31
+ const { handleNewQuery: w, handleAnswer: b } = F();
32
+ return f(() => {
33
+ t.current && (i ? t.current.showModal() : t.current.close());
34
+ }, [i]), f(() => {
35
+ var k;
36
+ const y = (k = t.current) == null ? void 0 : k.querySelector("input");
37
+ y && y.focus();
38
38
  }, [c.current]), /* @__PURE__ */ e(
39
- b,
39
+ L,
40
40
  {
41
- integrationId: t.kapaIntegrationId || "",
41
+ integrationId: a.kapaIntegrationId || "",
42
42
  callbacks: {
43
43
  askAI: {
44
- onQuerySubmit: A,
45
- onAnswerGenerationCompleted: I
44
+ onQuerySubmit: w,
45
+ onAnswerGenerationCompleted: b
46
46
  }
47
47
  },
48
48
  children: /* @__PURE__ */ e(
49
- K,
49
+ P,
50
50
  {
51
- ref: a,
52
- className: `n-search-modal ${o || ""}`,
51
+ ref: t,
52
+ className: `n-search-modal ${s || ""}`,
53
53
  "data-state": c.current,
54
54
  ...T,
55
- children: /* @__PURE__ */ e("div", { ref: v, className: "n-search-container", children: [
56
- c.current === "ask" && /* @__PURE__ */ e(w, { setModalState: s, initialQuery: r.searchTerm }),
55
+ children: /* @__PURE__ */ e("div", { ref: I, className: "n-search-container", children: [
56
+ c.current === "ask" && /* @__PURE__ */ e(
57
+ K,
58
+ {
59
+ setModalState: o,
60
+ searchQuery: r.searchTerm,
61
+ urlParamQuery: v
62
+ }
63
+ ),
57
64
  c.current === "search" && /* @__PURE__ */ e(N, { children: [
58
- /* @__PURE__ */ e(M, { setSearchTerm: p.setSearchTerm, initialValue: r.searchTerm }),
65
+ /* @__PURE__ */ e(O, { setSearchTerm: S.setSearchTerm, initialValue: r.searchTerm }),
59
66
  /* @__PURE__ */ e(
60
- L,
67
+ M,
61
68
  {
62
- setModalState: s,
69
+ setModalState: o,
63
70
  searchLoading: r.isLoading,
64
71
  searchTerm: r.searchTerm,
65
72
  results: r.results,
66
73
  children: /* @__PURE__ */ e(N, { children: [
67
- t.kapaIntegrationId && /* @__PURE__ */ e(O, { searchTerm: r.searchTerm, setModalState: s }),
74
+ a.kapaIntegrationId && /* @__PURE__ */ e(Q, { searchTerm: r.searchTerm, setModalState: o }),
68
75
  n
69
76
  ] })
70
77
  }
71
78
  ),
72
79
  /* @__PURE__ */ e("div", { className: "n-search-footer", children: [
73
80
  /* @__PURE__ */ e("p", { className: "n-search-footer-tip", children: [
74
- /* @__PURE__ */ e(d, { keyNames: ["Esc"] }),
81
+ /* @__PURE__ */ e(h, { keyNames: ["Esc"] }),
75
82
  "to close"
76
83
  ] }),
77
84
  /* @__PURE__ */ e("p", { className: "n-search-footer-tip", children: [
78
- /* @__PURE__ */ e(d, { keyNames: ["Tab"] }),
85
+ /* @__PURE__ */ e(h, { keyNames: ["Tab"] }),
79
86
  /* @__PURE__ */ e("span", { children: "or" }),
80
- /* @__PURE__ */ e(d, { keyNames: ["↑", "↓"] }),
87
+ /* @__PURE__ */ e(h, { keyNames: ["↑", "↓"] }),
81
88
  "to navigate"
82
89
  ] })
83
90
  ] })
@@ -89,5 +96,5 @@ function re(t = { className: "", children: void 0, debug: !1, kapaIntegrationId:
89
96
  );
90
97
  }
91
98
  export {
92
- re as default
99
+ te as default
93
100
  };
@@ -15,6 +15,6 @@
15
15
  * @param setSearchTerm - Function to update the search input state.
16
16
  * @param setModalState - (Optional) Function to set modal state, useful for distinguishing modal views.
17
17
  */
18
- export declare function useSearchParams(onOpen: () => void, setSearchTerm: (term: string) => void, setModalState?: (e: {
18
+ export declare function useSearchParams(onOpen: () => void, setSearchTerm: (term: string) => void, setUrlParamTerm: (term: string) => void, setModalState?: (e: {
19
19
  current: string;
20
20
  }) => void): void;
@@ -1,23 +1,23 @@
1
- import { d as u, y as t } from "../../../../chunks/hooks.module.DGkdD5n9.js";
2
- function l(s, a, r) {
3
- const [c, d] = u(!1);
1
+ import { d as h, y as t } from "../../../../chunks/hooks.module.DGkdD5n9.js";
2
+ function l(r, a, c, s) {
3
+ const [i, d] = h(!1);
4
4
  t(() => {
5
- let e;
6
- const n = () => {
7
- window.pagefind && (d(!0), e && clearInterval(e));
5
+ let n;
6
+ const e = () => {
7
+ window.pagefind && (d(!0), n && clearInterval(n));
8
8
  };
9
- return n(), e = setInterval(n, 100), () => clearInterval(e);
9
+ return e(), n = setInterval(e, 100), () => clearInterval(n);
10
10
  }, []), t(() => {
11
- if (typeof location > "u" || c) return;
12
- const e = new URLSearchParams(location.search), n = e.has("ask"), i = e.get("msg") || e.get("message"), o = e.get("search"), g = (f) => {
13
- f && a(f), r == null || r({ current: "ask" }), s();
11
+ if (typeof location > "u" || i) return;
12
+ const n = new URLSearchParams(location.search), e = n.has("ask"), f = n.get("msg") || n.get("message"), o = n.get("search"), u = (g) => {
13
+ g && c(g), s == null || s({ current: "ask" }), r();
14
14
  };
15
- if (n || i) {
16
- g(i);
15
+ if (e || f) {
16
+ u(f);
17
17
  return;
18
18
  }
19
- o && (a(o), s());
20
- }, [c]);
19
+ o && (a(o), r());
20
+ }, [i, r, s, a, c]);
21
21
  }
22
22
  export {
23
23
  l as useSearchParams
@@ -4,7 +4,7 @@ import { default as m } from "./Icon/index.js";
4
4
  import { default as s } from "./SearchModal/components/SearchLink/SearchLink.js";
5
5
  import { default as u } from "./SearchModal/components/SearchHeading/SearchHeading.js";
6
6
  import { default as i } from "./SearchModal/components/SearchToggle/SearchToggle.js";
7
- import { A as S } from "../../chunks/AskNetlify.hLTCaFLd.js";
7
+ import { A as S } from "../../chunks/AskNetlify.WwftmboN.js";
8
8
  import "preact";
9
9
  import "../../chunks/hooks.module.DGkdD5n9.js";
10
10
  import { default as n } from "./SearchModal/components/SearchModal/SearchModal.js";
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": "1.14.0",
4
+ "version": "1.14.1",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -11,10 +11,11 @@ import './AskNetlify.css';
11
11
 
12
12
  interface Props {
13
13
  setModalState?: (e: { current: string }) => void;
14
- initialQuery?: string;
14
+ searchQuery?: string;
15
+ urlParamQuery?: string;
15
16
  }
16
17
 
17
- export default function AskNetlify({ setModalState, initialQuery }: Props) {
18
+ export default function AskNetlify({ setModalState, searchQuery, urlParamQuery }: Props) {
18
19
  const [message, setMessage] = useState('');
19
20
  const [newMessageReady, setNewMessageReady] = useState(false);
20
21
  const chatRef = useRef<HTMLDivElement>(null);
@@ -50,35 +51,34 @@ export default function AskNetlify({ setModalState, initialQuery }: Props) {
50
51
  }
51
52
  }, [newMessageReady]);
52
53
 
54
+ /**
55
+ * Populates and handles the input when a query is present.
56
+ *
57
+ * - If `urlParamQuery` exists, pre-fills the input and waits for user action.
58
+ * - If `searchQuery` exists, auto-submits the query.
59
+ *
60
+ * Focuses the input and marks the message as ready in both cases.
61
+ */
53
62
  useEffect(() => {
54
- if (!initialQuery) return;
55
-
56
- const trimmedQuery = initialQuery.trim();
57
-
58
- /**
59
- * When reCAPTCHA is ready, we know this was triggered by a user action
60
- * (like clicking a button), so we can safely submit the query right away.
61
- * If reCAPTCHA isn't ready, the modal was likely opened from an outside source,
62
- * in that case, we populate the input and focus it, requiring manual submission
63
- * to ensure a user action triggers reCAPTCHA.
64
- */
65
- if (window.grecaptcha) {
66
- window.grecaptcha.enterprise.ready(() => {
67
- submitQuery(trimmedQuery);
68
- });
69
- } else {
63
+ const trimmedQuery = (urlParamQuery ?? searchQuery ?? '').trim();
64
+
65
+ if (urlParamQuery) {
70
66
  setMessage(trimmedQuery);
71
- inputRef?.current?.focus();
72
67
  }
73
68
 
69
+ if (searchQuery) {
70
+ submitQuery(trimmedQuery);
71
+ }
72
+
73
+ inputRef?.current?.focus();
74
74
  setNewMessageReady(true);
75
- }, [initialQuery]);
75
+ }, [setMessage, setNewMessageReady, submitQuery, setMessage, urlParamQuery, searchQuery]);
76
76
 
77
77
  return (
78
78
  <div className="n-ask-chat-container">
79
79
  <BackButton onClick={() => setModalState?.({ current: 'search' })} />
80
80
  <div ref={chatRef} className="n-ask-conversation n-search-window">
81
- {!conversation.length && !initialQuery && (
81
+ {!conversation.length && !urlParamQuery && !searchQuery && (
82
82
  <QuestionList onClick={handleSubmit} menuRef={menuRef} />
83
83
  )}
84
84
 
@@ -37,6 +37,7 @@ function SearchModal(
37
37
 
38
38
  const [modalState, setModalState] = useState({ current: 'search' });
39
39
  const [searchOpen, setSearchOpen] = useState(false);
40
+ const [urlParamTerm, setUrlParamTerm] = useState('');
40
41
  const openSearch = () => setSearchOpen(true);
41
42
  const closeSearch = () => setSearchOpen(false);
42
43
 
@@ -45,7 +46,7 @@ function SearchModal(
45
46
 
46
47
  const { state, actions } = useSearch();
47
48
  useSearchToggles(openSearch, setModalState);
48
- useSearchParams(openSearch, actions.setSearchTerm, setModalState);
49
+ useSearchParams(openSearch, actions.setSearchTerm, setUrlParamTerm, setModalState);
49
50
  useSearchHotkeys(searchOpen, openSearch, closeSearch);
50
51
  useKeyboardNav(modalRef, searchOpen, closeSearch);
51
52
  useSearchAnalytics(state, debug);
@@ -79,7 +80,11 @@ function SearchModal(
79
80
  >
80
81
  <div ref={containerRef} className="n-search-container">
81
82
  {modalState.current === 'ask' && (
82
- <AskNetlify setModalState={setModalState} initialQuery={state.searchTerm} />
83
+ <AskNetlify
84
+ setModalState={setModalState}
85
+ searchQuery={state.searchTerm}
86
+ urlParamQuery={urlParamTerm}
87
+ />
83
88
  )}
84
89
  {modalState.current === 'search' && (
85
90
  <>
@@ -21,6 +21,7 @@ import { useEffect, useState } from 'preact/hooks';
21
21
  export function useSearchParams(
22
22
  onOpen: () => void,
23
23
  setSearchTerm: (term: string) => void,
24
+ setUrlParamTerm: (term: string) => void,
24
25
  setModalState?: (e: { current: string }) => void
25
26
  ) {
26
27
  const [isPagefindLoaded, setIsPagefindLoaded] = useState(false);
@@ -54,7 +55,7 @@ export function useSearchParams(
54
55
  const search = params.get('search');
55
56
 
56
57
  const openAskModal = (term?: string | null) => {
57
- if (term) setSearchTerm(term);
58
+ if (term) setUrlParamTerm(term);
58
59
  setModalState?.({ current: 'ask' });
59
60
  onOpen();
60
61
  };
@@ -68,5 +69,5 @@ export function useSearchParams(
68
69
  setSearchTerm(search);
69
70
  onOpen();
70
71
  }
71
- }, [isPagefindLoaded]);
72
+ }, [isPagefindLoaded, onOpen, setModalState, setSearchTerm, setUrlParamTerm]);
72
73
  }