@tooee/search 0.1.21 → 0.2.0

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,6 +1,18 @@
1
1
  export interface UseSearchOptions {
2
2
  match: (query: string) => number[];
3
3
  onJump: (index: number) => void;
4
+ /**
5
+ * Register the search commands (default true). `false` leaves the state
6
+ * inert: no `/`, `n`, `shift+n` or cancel command exists.
7
+ */
8
+ enabled?: boolean;
9
+ /**
10
+ * Values the searched content is derived from. Matches are memoized on the
11
+ * query, so a committed query goes stale when the content changes underneath
12
+ * it (streaming or reloaded documents). List the content here to re-match.
13
+ * The array length must be stable across renders.
14
+ */
15
+ deps?: readonly unknown[];
4
16
  }
5
17
  export interface SearchState {
6
18
  searchQuery: string;
@@ -10,5 +22,5 @@ export interface SearchState {
10
22
  currentMatchIndex: number;
11
23
  submitSearch: () => void;
12
24
  }
13
- export declare function useSearch({ match, onJump }: UseSearchOptions): SearchState;
25
+ export declare function useSearch({ match, onJump, enabled, deps, }: UseSearchOptions): SearchState;
14
26
  //# sourceMappingURL=search-hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-hook.d.ts","sourceRoot":"","sources":["../src/search-hook.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB;AAMD,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,gBAAgB,GAAG,WAAW,CA6H1E"}
1
+ {"version":3,"file":"search-hook.d.ts","sourceRoot":"","sources":["../src/search-hook.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB;AAkBD,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,MAAM,EACN,OAAc,EACd,IAAiB,GAClB,EAAE,gBAAgB,GAAG,WAAW,CA6IhC"}
@@ -1,9 +1,15 @@
1
- import { useCallback, useMemo, useRef, useState } from "react";
1
+ import { useCallback, useRef, useState } from "react";
2
2
  import { useCommand, useMode, useSetMode } from "@tooee/commands";
3
3
  const EMPTY = [];
4
+ const EMPTY_DEPS = [];
5
+ function sameDeps(left, right) {
6
+ if (left.length !== right.length)
7
+ return false;
8
+ return left.every((value, index) => Object.is(value, right[index]));
9
+ }
4
10
  const CURSOR_MODES = ["cursor"];
5
11
  const ALL_MODES = ["cursor", "select", "insert"];
6
- export function useSearch({ match, onJump }) {
12
+ export function useSearch({ match, onJump, enabled = true, deps = EMPTY_DEPS, }) {
7
13
  const mode = useMode();
8
14
  const setMode = useSetMode();
9
15
  const [searchQuery, setSearchQuery] = useState("");
@@ -16,11 +22,24 @@ export function useSearch({ match, onJump }) {
16
22
  const onJumpRef = useRef(onJump);
17
23
  onJumpRef.current = onJump;
18
24
  const activeQuery = searchActive ? searchQuery : committedQuery;
19
- const matchingLines = useMemo(() => {
20
- if (!activeQuery)
21
- return EMPTY;
22
- return matchRef.current(activeQuery);
23
- }, [activeQuery]);
25
+ // Memoized on the query *and* the searched content: a committed query must
26
+ // re-match when rows arrive or change. `deps` is caller-sized, so this is a
27
+ // hand-rolled cache rather than a useMemo dependency array.
28
+ const cacheRef = useRef(null);
29
+ let matchingLines;
30
+ if (!activeQuery) {
31
+ matchingLines = EMPTY;
32
+ }
33
+ else {
34
+ const cache = cacheRef.current;
35
+ if (cache && cache.query === activeQuery && sameDeps(cache.deps, deps)) {
36
+ matchingLines = cache.matches;
37
+ }
38
+ else {
39
+ matchingLines = matchRef.current(activeQuery);
40
+ cacheRef.current = { query: activeQuery, deps: [...deps], matches: matchingLines };
41
+ }
42
+ }
24
43
  const matchingLinesRef = useRef(matchingLines);
25
44
  matchingLinesRef.current = matchingLines;
26
45
  // Imperatively set search query, reset match index, and jump to first match.
@@ -37,6 +56,7 @@ export function useSearch({ match, onJump }) {
37
56
  title: "Search",
38
57
  hotkey: "/",
39
58
  modes: CURSOR_MODES,
59
+ enabled,
40
60
  handler: () => {
41
61
  preSearchModeRef.current = mode;
42
62
  setSearchActive(true);
@@ -49,6 +69,7 @@ export function useSearch({ match, onJump }) {
49
69
  title: "Next match",
50
70
  hotkey: "n",
51
71
  modes: CURSOR_MODES,
72
+ enabled,
52
73
  when: () => !searchActive,
53
74
  handler: () => {
54
75
  const matches = matchingLinesRef.current;
@@ -69,6 +90,7 @@ export function useSearch({ match, onJump }) {
69
90
  title: "Previous match",
70
91
  hotkey: "shift+n",
71
92
  modes: CURSOR_MODES,
93
+ enabled,
72
94
  when: () => !searchActive,
73
95
  handler: () => {
74
96
  const matches = matchingLinesRef.current;
@@ -89,6 +111,7 @@ export function useSearch({ match, onJump }) {
89
111
  title: "Cancel search",
90
112
  hotkey: "escape",
91
113
  modes: ALL_MODES,
114
+ enabled,
92
115
  when: () => searchActive,
93
116
  handler: () => {
94
117
  setSearchActive(false);
@@ -1 +1 @@
1
- {"version":3,"file":"search-hook.js","sourceRoot":"","sources":["../src/search-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC9D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAa,MAAM,iBAAiB,CAAA;AAgB5E,MAAM,KAAK,GAAa,EAAE,CAAA;AAC1B,MAAM,YAAY,GAAW,CAAC,QAAQ,CAAC,CAAA;AACvC,MAAM,SAAS,GAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAExD,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAoB;IAC3D,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAA;IAE5B,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAClD,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IACvD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;IAC7D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACxD,MAAM,gBAAgB,GAAG,MAAM,CAAO,QAAQ,CAAC,CAAA;IAE/C,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC9B,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAA;IAExB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAA;IAChC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAA;IAE1B,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAA;IAE/D,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAA;QAC9B,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACtC,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,MAAM,gBAAgB,GAAG,MAAM,CAAC,aAAa,CAAC,CAAA;IAC9C,gBAAgB,CAAC,OAAO,GAAG,aAAa,CAAA;IAExC,6EAA6E;IAC7E,MAAM,iBAAiB,GAAG,WAAW,CAAC,CAAC,KAAa,EAAE,EAAE;QACtD,cAAc,CAAC,KAAK,CAAC,CAAA;QACrB,oBAAoB,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACpD,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YACvB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,UAAU,CAAC;QACT,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,GAAG,EAAE;YACZ,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;YAC/B,eAAe,CAAC,IAAI,CAAC,CAAA;YACrB,cAAc,CAAC,EAAE,CAAC,CAAA;YAClB,OAAO,CAAC,QAAQ,CAAC,CAAA;QACnB,CAAC;KACF,CAAC,CAAA;IAEF,UAAU,CAAC;QACT,EAAE,EAAE,oBAAoB;QACxB,KAAK,EAAE,YAAY;QACnB,MAAM,EAAE,GAAG;QACX,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY;QACzB,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAA;YACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAEhC,oBAAoB,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC7B,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAA;gBAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;gBACpC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;oBACtB,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;gBAC9B,CAAC;gBACD,OAAO,SAAS,CAAA;YAClB,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IAEF,UAAU,CAAC;QACT,EAAE,EAAE,oBAAoB;QACxB,KAAK,EAAE,gBAAgB;QACvB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,YAAY;QACnB,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,YAAY;QACzB,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAA;YACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAEhC,oBAAoB,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC7B,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAA;gBAC/D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;gBACpC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;oBACtB,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;gBAC9B,CAAC;gBACD,OAAO,SAAS,CAAA;YAClB,CAAC,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IAEF,UAAU,CAAC;QACT,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY;QACxB,OAAO,EAAE,GAAG,EAAE;YACZ,eAAe,CAAC,KAAK,CAAC,CAAA;YACtB,cAAc,CAAC,EAAE,CAAC,CAAA;YAClB,iBAAiB,CAAC,EAAE,CAAC,CAAA;YACrB,oBAAoB,CAAC,CAAC,CAAC,CAAA;YACvB,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;QACnC,CAAC;KACF,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;QACpC,iBAAiB,CAAC,WAAW,CAAC,CAAA;QAC9B,eAAe,CAAC,KAAK,CAAC,CAAA;QACtB,oBAAoB,CAAC,CAAC,CAAC,CAAA;QACvB,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAChE,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YACvB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/B,CAAC;QACD,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACnC,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAA;IAE1B,OAAO;QACL,WAAW;QACX,YAAY;QACZ,cAAc,EAAE,iBAAiB;QACjC,aAAa;QACb,iBAAiB;QACjB,YAAY;KACb,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"search-hook.js","sourceRoot":"","sources":["../src/search-hook.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tooee/search",
3
- "version": "0.1.21",
3
+ "version": "0.2.0",
4
4
  "description": "Search hook, utilities, and SearchBar component for Tooee",
5
5
  "keywords": [
6
6
  "cli",
@@ -35,19 +35,19 @@
35
35
  "typecheck": "tsc --noEmit"
36
36
  },
37
37
  "dependencies": {
38
- "@tooee/commands": "0.1.21",
39
- "@tooee/themes": "0.1.21"
38
+ "@tooee/commands": "0.2.0",
39
+ "@tooee/themes": "0.2.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@opentui/core": "^0.2.15",
43
- "@opentui/react": "^0.2.15",
42
+ "@opentui/core": "^0.4.3",
43
+ "@opentui/react": "^0.4.3",
44
44
  "@types/bun": "^1.3.10",
45
45
  "@types/react": "^19.2.14",
46
46
  "typescript": "^5.9.3"
47
47
  },
48
48
  "peerDependencies": {
49
- "@opentui/core": "^0.2.15",
50
- "@opentui/react": "^0.2.15",
49
+ "@opentui/core": "^0.4.3",
50
+ "@opentui/react": "^0.4.3",
51
51
  "react": "^18.0.0 || ^19.0.0"
52
52
  }
53
53
  }
@@ -1,9 +1,21 @@
1
- import { useCallback, useMemo, useRef, useState } from "react"
1
+ import { useCallback, useRef, useState } from "react"
2
2
  import { useCommand, useMode, useSetMode, type Mode } from "@tooee/commands"
3
3
 
4
4
  export interface UseSearchOptions {
5
5
  match: (query: string) => number[]
6
6
  onJump: (index: number) => void
7
+ /**
8
+ * Register the search commands (default true). `false` leaves the state
9
+ * inert: no `/`, `n`, `shift+n` or cancel command exists.
10
+ */
11
+ enabled?: boolean
12
+ /**
13
+ * Values the searched content is derived from. Matches are memoized on the
14
+ * query, so a committed query goes stale when the content changes underneath
15
+ * it (streaming or reloaded documents). List the content here to re-match.
16
+ * The array length must be stable across renders.
17
+ */
18
+ deps?: readonly unknown[]
7
19
  }
8
20
 
9
21
  export interface SearchState {
@@ -16,10 +28,27 @@ export interface SearchState {
16
28
  }
17
29
 
18
30
  const EMPTY: number[] = []
31
+ const EMPTY_DEPS: readonly unknown[] = []
32
+
33
+ interface MatchCache {
34
+ query: string
35
+ deps: readonly unknown[]
36
+ matches: number[]
37
+ }
38
+
39
+ function sameDeps(left: readonly unknown[], right: readonly unknown[]): boolean {
40
+ if (left.length !== right.length) return false
41
+ return left.every((value, index) => Object.is(value, right[index]))
42
+ }
19
43
  const CURSOR_MODES: Mode[] = ["cursor"]
20
44
  const ALL_MODES: Mode[] = ["cursor", "select", "insert"]
21
45
 
22
- export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
46
+ export function useSearch({
47
+ match,
48
+ onJump,
49
+ enabled = true,
50
+ deps = EMPTY_DEPS,
51
+ }: UseSearchOptions): SearchState {
23
52
  const mode = useMode()
24
53
  const setMode = useSetMode()
25
54
 
@@ -37,10 +66,22 @@ export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
37
66
 
38
67
  const activeQuery = searchActive ? searchQuery : committedQuery
39
68
 
40
- const matchingLines = useMemo(() => {
41
- if (!activeQuery) return EMPTY
42
- return matchRef.current(activeQuery)
43
- }, [activeQuery])
69
+ // Memoized on the query *and* the searched content: a committed query must
70
+ // re-match when rows arrive or change. `deps` is caller-sized, so this is a
71
+ // hand-rolled cache rather than a useMemo dependency array.
72
+ const cacheRef = useRef<MatchCache | null>(null)
73
+ let matchingLines: number[]
74
+ if (!activeQuery) {
75
+ matchingLines = EMPTY
76
+ } else {
77
+ const cache = cacheRef.current
78
+ if (cache && cache.query === activeQuery && sameDeps(cache.deps, deps)) {
79
+ matchingLines = cache.matches
80
+ } else {
81
+ matchingLines = matchRef.current(activeQuery)
82
+ cacheRef.current = { query: activeQuery, deps: [...deps], matches: matchingLines }
83
+ }
84
+ }
44
85
 
45
86
  const matchingLinesRef = useRef(matchingLines)
46
87
  matchingLinesRef.current = matchingLines
@@ -60,6 +101,7 @@ export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
60
101
  title: "Search",
61
102
  hotkey: "/",
62
103
  modes: CURSOR_MODES,
104
+ enabled,
63
105
  handler: () => {
64
106
  preSearchModeRef.current = mode
65
107
  setSearchActive(true)
@@ -73,6 +115,7 @@ export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
73
115
  title: "Next match",
74
116
  hotkey: "n",
75
117
  modes: CURSOR_MODES,
118
+ enabled,
76
119
  when: () => !searchActive,
77
120
  handler: () => {
78
121
  const matches = matchingLinesRef.current
@@ -94,6 +137,7 @@ export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
94
137
  title: "Previous match",
95
138
  hotkey: "shift+n",
96
139
  modes: CURSOR_MODES,
140
+ enabled,
97
141
  when: () => !searchActive,
98
142
  handler: () => {
99
143
  const matches = matchingLinesRef.current
@@ -115,6 +159,7 @@ export function useSearch({ match, onJump }: UseSearchOptions): SearchState {
115
159
  title: "Cancel search",
116
160
  hotkey: "escape",
117
161
  modes: ALL_MODES,
162
+ enabled,
118
163
  when: () => searchActive,
119
164
  handler: () => {
120
165
  setSearchActive(false)