@ox0/hooks 0.2.2 → 0.3.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -1
- package/dist/use-search-history.d.ts +24 -0
- package/dist/use-search-history.d.ts.map +1 -0
- package/dist/use-search-history.test.d.ts +2 -0
- package/dist/use-search-history.test.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./use-hover";
|
|
|
11
11
|
export * from "./use-interval";
|
|
12
12
|
export * from "./use-key-down";
|
|
13
13
|
export * from "./use-stored-state";
|
|
14
|
+
export * from "./use-search-history";
|
|
14
15
|
export * from "./use-long-press";
|
|
15
16
|
export * from "./use-press";
|
|
16
17
|
export * from "./use-media-query";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAA;AAC3C,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kBAAkB,CAAA;AAChC,cAAc,sBAAsB,CAAA;AACpC,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,sBAAsB,CAAA;AACpC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -502,6 +502,49 @@ function useSessionState(key, parser, options) {
|
|
|
502
502
|
function useSessionSharedState(key, parser, options) {
|
|
503
503
|
return useStoredState("session", key, parser, options, true);
|
|
504
504
|
}
|
|
505
|
+
const entriesParser = {
|
|
506
|
+
parse (value) {
|
|
507
|
+
if (!Array.isArray(value)) throw new Error("search history is not a list");
|
|
508
|
+
return value.filter((entry)=>"string" == typeof entry);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
function searchHistoryIdentity(entry) {
|
|
512
|
+
return entry.trim().replace(/\s+/g, " ").toLowerCase();
|
|
513
|
+
}
|
|
514
|
+
function useSearchHistory(key, options = {}) {
|
|
515
|
+
const { limit = 15, storage = "persistent" } = options;
|
|
516
|
+
const storageKey = `search-history:${key}`;
|
|
517
|
+
const persistent = usePersistentSharedState(storageKey, entriesParser, {
|
|
518
|
+
defaultValue: []
|
|
519
|
+
});
|
|
520
|
+
const session = useSessionSharedState(storageKey, entriesParser, {
|
|
521
|
+
defaultValue: []
|
|
522
|
+
});
|
|
523
|
+
const [entries, setEntries] = "session" === storage ? session : persistent;
|
|
524
|
+
return useMemo(()=>({
|
|
525
|
+
entries,
|
|
526
|
+
add (entry) {
|
|
527
|
+
const text = entry.trim();
|
|
528
|
+
if ("" === text) return;
|
|
529
|
+
const identity = searchHistoryIdentity(text);
|
|
530
|
+
setEntries((previous)=>[
|
|
531
|
+
text,
|
|
532
|
+
...previous.filter((existing)=>searchHistoryIdentity(existing) !== identity)
|
|
533
|
+
].slice(0, limit));
|
|
534
|
+
},
|
|
535
|
+
remove (entry) {
|
|
536
|
+
const identity = searchHistoryIdentity(entry);
|
|
537
|
+
setEntries((previous)=>previous.filter((existing)=>searchHistoryIdentity(existing) !== identity));
|
|
538
|
+
},
|
|
539
|
+
clear () {
|
|
540
|
+
setEntries([]);
|
|
541
|
+
}
|
|
542
|
+
}), [
|
|
543
|
+
entries,
|
|
544
|
+
limit,
|
|
545
|
+
setEntries
|
|
546
|
+
]);
|
|
547
|
+
}
|
|
505
548
|
function useLongPress({ delayMs = 500, moveThresholdPx = 8, disabled = false, onLongPress }) {
|
|
506
549
|
const timerRef = useRef(null);
|
|
507
550
|
const pointerIdRef = useRef(null);
|
|
@@ -717,4 +760,4 @@ function useWindowSize() {
|
|
|
717
760
|
return size;
|
|
718
761
|
}
|
|
719
762
|
export { isFocusVisible, usePress } from "@react-aria/interactions";
|
|
720
|
-
export { StorageProvider, useBeforeUnloadWarning, useBreakpoint, useContainerSize, useControllableState, useCopyToClipboard, useDebouncedValue, useDeferredPresence, useDisclosure, useEventListener, useHover, useInterval, useKeyDown, useLongPress, useMediaQuery, useNavigatorOnline, useNow, useOS, usePersistentSharedState, usePersistentState, usePointerCoarse, usePrefersReducedMotion, usePrevious, useSessionSharedState, useSessionState, useTimeout, useViewport, useWindowSize };
|
|
763
|
+
export { StorageProvider, useBeforeUnloadWarning, useBreakpoint, useContainerSize, useControllableState, useCopyToClipboard, useDebouncedValue, useDeferredPresence, useDisclosure, useEventListener, useHover, useInterval, useKeyDown, useLongPress, useMediaQuery, useNavigatorOnline, useNow, useOS, usePersistentSharedState, usePersistentState, usePointerCoarse, usePrefersReducedMotion, usePrevious, useSearchHistory, useSessionSharedState, useSessionState, useTimeout, useViewport, useWindowSize };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Recent searches, newest first. Pass it to a search box (`QueryBar`, `GlobalSearch`) as `history`. */
|
|
2
|
+
export type SearchHistory = {
|
|
3
|
+
readonly entries: readonly string[];
|
|
4
|
+
/** Records a search: moves it (or an earlier copy of it) to the top, and trims to the limit. */
|
|
5
|
+
readonly add: (entry: string) => void;
|
|
6
|
+
readonly remove: (entry: string) => void;
|
|
7
|
+
readonly clear: () => void;
|
|
8
|
+
};
|
|
9
|
+
export type SearchHistoryOptions = {
|
|
10
|
+
/** How many entries to keep. Default 15. */
|
|
11
|
+
readonly limit?: number;
|
|
12
|
+
/**
|
|
13
|
+
* `"persistent"` (default): kept across sessions in localStorage. `"session"`: forgotten when the
|
|
14
|
+
* tab closes — consider it when searches can contain personal data.
|
|
15
|
+
*/
|
|
16
|
+
readonly storage?: "persistent" | "session";
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Recent searches for one search box, kept per user through `StorageProvider` and shared between
|
|
20
|
+
* tabs. Entries are deduplicated ignoring case and spacing; blank searches aren't recorded. Use a
|
|
21
|
+
* key per box (`"payments"`, `"global-search"`) so their histories stay apart.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useSearchHistory(key: string, options?: SearchHistoryOptions): SearchHistory;
|
|
24
|
+
//# sourceMappingURL=use-search-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-search-history.d.ts","sourceRoot":"","sources":["../src/use-search-history.ts"],"names":[],"mappings":"AAIA,wGAAwG;AACxG,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,gGAAgG;IAChG,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;CAC5C,CAAA;AAcD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAiC/F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-search-history.test.d.ts","sourceRoot":"","sources":["../src/use-search-history.test.tsx"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ox0/hooks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/esturcke/ox0-platform.git",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"react": "^19.0.0"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
|
-
"build": "rslib build -c ../../rslib.config.ts &&
|
|
30
|
+
"build": "rslib build -c ../../rslib.config.ts && rm -f tsconfig.build.tsbuildinfo && tsc -p tsconfig.build.json",
|
|
31
31
|
"typecheck": "tsc -p tsconfig.json",
|
|
32
32
|
"lint": "oxlint .",
|
|
33
33
|
"test": "vitest run"
|